about summary refs log tree commit diff
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
parent14cfc3ade4538ecf6f684962521685664348b522 (diff)
parentf80cac723acf10a8f9fd05b335ed5797e4f69a1a (diff)
downloadrust-b178f22bd8267155f2e330731a53ef3e4eac28bb.tar.gz
rust-b178f22bd8267155f2e330731a53ef3e4eac28bb.zip
Merge pull request #4220 from rust-lang/rustup-2025-03-06
Automatic Rustup
-rw-r--r--.github/workflows/ci.yml42
-rw-r--r--.mailmap3
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--INSTALL.md10
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs11
-rw-r--r--compiler/rustc_ast/src/ast.rs50
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs15
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs18
-rw-r--r--compiler/rustc_ast/src/token.rs296
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs2
-rw-r--r--compiler/rustc_ast/src/util/parser.rs42
-rw-r--r--compiler/rustc_ast/src/visit.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs17
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs45
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch4
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs18
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs44
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs218
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs373
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs86
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs59
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs26
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs56
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/consts.rs1
-rw-r--r--compiler/rustc_data_structures/src/captures.rs8
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs16
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs33
-rw-r--r--compiler/rustc_data_structures/src/sync.rs67
-rw-r--r--compiler/rustc_data_structures/src/sync/worker_local.rs11
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0373.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0804.md41
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/base.rs16
-rw-r--r--compiler/rustc_expand/src/config.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs38
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs4
-rw-r--r--compiler/rustc_expand/src/placeholders.rs24
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs71
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs7
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs6
-rw-r--r--compiler/rustc_hir/src/target.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs82
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs327
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs10
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs75
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl9
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs12
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/lib.rs5
-rw-r--r--compiler/rustc_lint/src/types.rs30
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs55
-rw-r--r--compiler/rustc_metadata/messages.ftl3
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs21
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs4
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs37
-rw-r--r--compiler/rustc_middle/src/query/keys.rs8
-rw-r--r--compiler/rustc_middle/src/query/mod.rs13
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs20
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs108
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/match_pair.rs217
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs59
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/simplify.rs71
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs17
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/util.rs8
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs29
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs6
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs36
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs18
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs34
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs49
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs18
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs12
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs25
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs46
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs65
-rw-r--r--compiler/rustc_parse/src/parser/item.rs28
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs8
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs18
-rw-r--r--compiler/rustc_parse/src/parser/path.rs5
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs15
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs2
-rw-r--r--compiler/rustc_parse/src/parser/token_type.rs25
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs26
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs50
-rw-r--r--compiler/rustc_passes/src/errors.rs8
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs17
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs8
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs22
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs6
-rw-r--r--compiler/rustc_session/src/config.rs72
-rw-r--r--compiler/rustc_session/src/utils.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs55
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs1
-rw-r--r--compiler/rustc_target/src/target_features.rs1
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/regions.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs198
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs31
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs28
-rw-r--r--compiler/rustc_ty_utils/messages.ftl2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs7
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs6
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs3
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs89
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs5
-rw-r--r--compiler/stable_mir/src/crate_def.rs38
-rw-r--r--compiler/stable_mir/src/lib.rs26
-rw-r--r--config.example.toml22
-rw-r--r--library/Cargo.lock8
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/alloc.rs10
-rw-r--r--library/alloc/src/boxed.rs4
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/string.rs3
-rw-r--r--library/core/src/fmt/mod.rs66
-rw-r--r--library/core/src/marker/variance.rs12
-rw-r--r--library/core/src/num/dec2flt/common.rs27
-rw-r--r--library/core/src/num/dec2flt/decimal.rs421
-rw-r--r--library/core/src/num/dec2flt/decimal_seq.rs379
-rw-r--r--library/core/src/num/dec2flt/float.rs272
-rw-r--r--library/core/src/num/dec2flt/lemire.rs22
-rw-r--r--library/core/src/num/dec2flt/mod.rs37
-rw-r--r--library/core/src/num/dec2flt/number.rs88
-rw-r--r--library/core/src/num/dec2flt/parse.rs10
-rw-r--r--library/core/src/num/dec2flt/slow.rs28
-rw-r--r--library/core/src/num/f32.rs6
-rw-r--r--library/core/src/num/f64.rs6
-rw-r--r--library/core/src/ops/bit.rs2
-rw-r--r--library/core/src/ops/range.rs2
-rw-r--r--library/core/src/slice/mod.rs34
-rw-r--r--library/coretests/tests/lib.rs2
-rw-r--r--library/coretests/tests/num/dec2flt/decimal.rs28
-rw-r--r--library/coretests/tests/num/dec2flt/decimal_seq.rs30
-rw-r--r--library/coretests/tests/num/dec2flt/float.rs48
-rw-r--r--library/coretests/tests/num/dec2flt/lemire.rs10
-rw-r--r--library/coretests/tests/num/dec2flt/mod.rs2
-rw-r--r--library/coretests/tests/num/dec2flt/parse.rs41
-rw-r--r--library/coretests/tests/ptr.rs10
-rw-r--r--library/coretests/tests/slice.rs3
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/build.rs7
-rw-r--r--library/std/src/fs.rs8
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/io/stdio.rs34
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs61
-rw-r--r--library/std/src/sys/pal/uefi/process.rs2
-rw-r--r--library/std/src/sys/pal/unix/process/process_unix.rs17
-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
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect.rs32
-rw-r--r--tests/codegen/issues/looping-over-ne-bytes-133528.rs17
-rw-r--r--tests/codegen/slice-init.rs51
-rw-r--r--tests/crashes/129095.rs5
-rw-r--r--tests/crashes/132960.rs2
-rw-r--r--tests/crashes/132981.rs11
-rw-r--r--tests/crashes/134654.rs3
-rw-r--r--tests/crashes/135128.rs2
-rw-r--r--tests/crashes/135570.rs3
-rw-r--r--tests/debuginfo/unsized.rs21
-rw-r--r--tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff29
-rw-r--r--tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff41
-rw-r--r--tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs2
-rw-r--r--tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff32
-rw-r--r--tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff47
-rw-r--r--tests/mir-opt/inline/inline_box_fn.rs2
-rw-r--r--tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff13
-rw-r--r--tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff13
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff24
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff40
-rw-r--r--tests/mir-opt/inline/inline_diverging.rs3
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff14
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff22
-rw-r--r--tests/mir-opt/inline/issue_78442.rs5
-rw-r--r--tests/mir-opt/inline_fn_call_for_fn_def.rs19
-rw-r--r--tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff34
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir (renamed from tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir)0
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir (renamed from tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir)0
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir68
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir68
-rw-r--r--tests/mir-opt/issues/issue_59352.rs2
-rw-r--r--tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir6
-rw-r--r--tests/run-make/README.md36
-rw-r--r--tests/run-make/a-b-a-linker-guard/rmake.rs7
-rw-r--r--tests/run-make/linker-warning/rmake.rs2
-rw-r--r--tests/run-make/linker-warning/short-error.txt2
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs11
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt1
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs20
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim/library.c3
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim/main.rs11
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim/output.txt1
-rw-r--r--tests/run-make/raw-dylib-elf-verbatim/rmake.rs31
-rw-r--r--tests/run-make/raw-dylib-elf/library.c3
-rw-r--r--tests/run-make/raw-dylib-elf/main.rs11
-rw-r--r--tests/run-make/raw-dylib-elf/output.txt1
-rw-r--r--tests/run-make/raw-dylib-elf/rmake.rs29
-rw-r--r--tests/run-make/reproducible-build/linker.rs2
-rw-r--r--tests/run-make/rustc-help/help-v.stdout2
-rw-r--r--tests/run-make/rustc-help/help.stdout2
-rw-r--r--tests/run-make/rustdoc-default-output/output-default.stdout2
-rw-r--r--tests/run-make/rustdoc-default-output/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-dep-info/bar.rs1
-rw-r--r--tests/run-make/rustdoc-dep-info/doc.md1
-rw-r--r--tests/run-make/rustdoc-dep-info/foo.rs1
-rw-r--r--tests/run-make/rustdoc-dep-info/lib.rs6
-rw-r--r--tests/run-make/rustdoc-dep-info/rmake.rs21
-rw-r--r--tests/run-make/tools.mk209
-rw-r--r--tests/run-make/version-verbose-commit-hash/rmake.rs4
-rw-r--r--tests/rustdoc-json/enums/discriminant/limits.rs1
-rw-r--r--tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs2
-rw-r--r--tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs2
-rw-r--r--tests/rustdoc-json/enums/discriminant/struct.rs2
-rw-r--r--tests/rustdoc-json/enums/discriminant/tuple.rs2
-rw-r--r--tests/rustdoc-json/enums/kind.rs2
-rw-r--r--tests/rustdoc-json/fn_pointer/abi.rs2
-rw-r--r--tests/rustdoc-json/fn_pointer/generics.rs2
-rw-r--r--tests/rustdoc-json/fn_pointer/qualifiers.rs2
-rw-r--r--tests/rustdoc-json/fns/abi.rs2
-rw-r--r--tests/rustdoc-json/fns/async_return.rs1
-rw-r--r--tests/rustdoc-json/fns/generic_args.rs2
-rw-r--r--tests/rustdoc-json/fns/generic_returns.rs2
-rw-r--r--tests/rustdoc-json/fns/generics.rs2
-rw-r--r--tests/rustdoc-json/generic-associated-types/gats.rs2
-rw-r--r--tests/rustdoc-json/impl-trait-in-assoc-type.rs1
-rw-r--r--tests/rustdoc-json/lifetime/longest.rs2
-rw-r--r--tests/rustdoc-json/lifetime/outlives.rs2
-rw-r--r--tests/rustdoc-json/lifetime/outlives_in_param.rs2
-rw-r--r--tests/rustdoc-json/lifetime/outlives_in_where.rs2
-rw-r--r--tests/rustdoc-json/methods/abi.rs2
-rw-r--r--tests/rustdoc-json/non_lifetime_binders.rs2
-rw-r--r--tests/rustdoc-json/path_name.rs1
-rw-r--r--tests/rustdoc-json/reexport/doc_inline_external_crate.rs1
-rw-r--r--tests/rustdoc-json/reexport/export_extern_crate_as_self.rs2
-rw-r--r--tests/rustdoc-json/reexport/private_twice_one_inline.rs1
-rw-r--r--tests/rustdoc-json/reexport/private_two_names.rs2
-rw-r--r--tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs2
-rw-r--r--tests/rustdoc-json/return_private.rs1
-rw-r--r--tests/rustdoc-json/statics/extern.rs1
-rw-r--r--tests/rustdoc-json/structs/with_primitives.rs2
-rw-r--r--tests/rustdoc-json/trait_alias.rs1
-rw-r--r--tests/rustdoc-json/traits/private_supertrait.rs2
-rw-r--r--tests/rustdoc-json/traits/self.rs2
-rw-r--r--tests/rustdoc-json/traits/supertrait.rs2
-rw-r--r--tests/rustdoc-json/traits/trait_alias.rs1
-rw-r--r--tests/rustdoc-json/type/dyn.rs1
-rw-r--r--tests/rustdoc-json/type/fn_lifetime.rs2
-rw-r--r--tests/rustdoc-json/type/generic_default.rs2
-rw-r--r--tests/rustdoc-json/type/hrtb.rs2
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type.rs1
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_bound.rs1
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_projections.rs1
-rw-r--r--tests/rustdoc-ui/issues/issue-79494.rs2
-rw-r--r--tests/rustdoc-ui/issues/issue-79494.stderr6
-rw-r--r--tests/rustdoc-ui/target-feature-stability.rs28
-rw-r--r--tests/rustdoc-ui/track-diagnostics.rs3
-rw-r--r--tests/rustdoc-ui/track-diagnostics.stderr4
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout4
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_ty_fold.rs12
-rw-r--r--tests/ui-fulldeps/stable-mir/crate-info.rs23
-rw-r--r--tests/ui-fulldeps/stable-mir/projections.rs10
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_internal.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_serde.rs24
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_visitor.rs12
-rw-r--r--tests/ui/abi/rust-cold-works-with-rustic-args.rs6
-rw-r--r--tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs7
-rw-r--r--tests/ui/abi/unsupported.aarch64.stderr110
-rw-r--r--tests/ui/abi/unsupported.arm.stderr99
-rw-r--r--tests/ui/abi/unsupported.i686.stderr77
-rw-r--r--tests/ui/abi/unsupported.riscv32.stderr99
-rw-r--r--tests/ui/abi/unsupported.riscv64.stderr99
-rw-r--r--tests/ui/abi/unsupported.x64.stderr99
-rw-r--r--tests/ui/associated-inherent-types/issue-109299-1.stderr4
-rw-r--r--tests/ui/associated-inherent-types/issue-109789.rs1
-rw-r--r--tests/ui/associated-inherent-types/issue-109789.stderr10
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.rs1
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.stderr10
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr2
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.stderr4
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr4
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr2
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.rs1
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.stderr14
-rw-r--r--tests/ui/attributes/auxiliary/used_pre_main_constructor.rs9
-rw-r--r--tests/ui/c-variadic/variadic-ffi-2.rs4
-rw-r--r--tests/ui/c-variadic/variadic-ffi-2.stderr6
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.rs16
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.stderr2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-add-auto.rs14
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-add-auto.stderr44
-rw-r--r--tests/ui/check-cfg/target_feature.stderr1
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr12
-rw-r--r--tests/ui/const-generics/mgca/ambiguous-assoc-const.rs15
-rw-r--r--tests/ui/const-generics/mgca/ambiguous-assoc-const.stderr15
-rw-r--r--tests/ui/const-generics/mgca/assoc-const-without-type_const.rs14
-rw-r--r--tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr18
-rw-r--r--tests/ui/const-generics/mgca/assoc-const.rs15
-rw-r--r--tests/ui/const-generics/mgca/bad-type_const-syntax.rs17
-rw-r--r--tests/ui/const-generics/mgca/bad-type_const-syntax.stderr35
-rw-r--r--tests/ui/const-generics/mgca/inherent-const-gating.rs13
-rw-r--r--tests/ui/const-generics/mgca/inherent-const-gating.stderr13
-rw-r--r--tests/ui/consts/const-slice-array-deref.stderr1
-rw-r--r--tests/ui/consts/const-unsized.stderr4
-rw-r--r--tests/ui/consts/const_refs_to_static-ice-121413.stderr1
-rw-r--r--tests/ui/consts/dont-ctfe-unsized-initializer.rs7
-rw-r--r--tests/ui/consts/dont-ctfe-unsized-initializer.stderr21
-rw-r--r--tests/ui/consts/issue-39974.stderr12
-rw-r--r--tests/ui/crate-loading/crateresolve1.stderr6
-rw-r--r--tests/ui/crate-loading/crateresolve2.stderr6
-rw-r--r--tests/ui/diagnostic-width/E0271.ascii.stderr6
-rw-r--r--tests/ui/diagnostic-width/E0271.rs1
-rw-r--r--tests/ui/diagnostic-width/E0271.unicode.stderr6
-rw-r--r--tests/ui/diagnostic-width/binop.rs2
-rw-r--r--tests/ui/diagnostic-width/binop.stderr8
-rw-r--r--tests/ui/diagnostic-width/long-E0308.ascii.stderr16
-rw-r--r--tests/ui/diagnostic-width/long-E0308.rs3
-rw-r--r--tests/ui/diagnostic-width/long-E0308.unicode.stderr16
-rw-r--r--tests/ui/diagnostic-width/long-E0529.rs3
-rw-r--r--tests/ui/diagnostic-width/long-E0529.stderr4
-rw-r--r--tests/ui/diagnostic-width/long-E0609.rs3
-rw-r--r--tests/ui/diagnostic-width/long-E0609.stderr4
-rw-r--r--tests/ui/diagnostic-width/long-E0614.rs3
-rw-r--r--tests/ui/diagnostic-width/long-E0614.stderr4
-rw-r--r--tests/ui/diagnostic-width/long-E0618.rs3
-rw-r--r--tests/ui/diagnostic-width/long-E0618.stderr4
-rw-r--r--tests/ui/diagnostic-width/long-e0277.rs2
-rw-r--r--tests/ui/diagnostic-width/long-e0277.stderr8
-rw-r--r--tests/ui/diagnostic-width/non-copy-type-moved.rs2
-rw-r--r--tests/ui/diagnostic-width/non-copy-type-moved.stderr4
-rw-r--r--tests/ui/diagnostic-width/secondary-label-with-long-type.rs2
-rw-r--r--tests/ui/diagnostic-width/secondary-label-with-long-type.stderr4
-rw-r--r--tests/ui/dst/dst-bad-assign-3.rs6
-rw-r--r--tests/ui/dst/dst-bad-assign-3.stderr4
-rw-r--r--tests/ui/dst/dst-bad-coerce1.rs14
-rw-r--r--tests/ui/dst/dst-bad-coerce1.stderr32
-rw-r--r--tests/ui/dst/dst-bad-coerce3.rs12
-rw-r--r--tests/ui/dst/dst-bad-coerce3.stderr38
-rw-r--r--tests/ui/dst/dst-bad-coerce4.rs10
-rw-r--r--tests/ui/dst/dst-bad-coerce4.stderr15
-rw-r--r--tests/ui/dst/dst-bad-deep-2.rs8
-rw-r--r--tests/ui/dst/dst-bad-deep-2.stderr18
-rw-r--r--tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs11
-rw-r--r--tests/ui/dynamically-sized-types/dst-raw.rs35
-rw-r--r--tests/ui/dynamically-sized-types/dst-trait-tuple.rs102
-rw-r--r--tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs26
-rw-r--r--tests/ui/dynamically-sized-types/dst-tuple-sole.rs79
-rw-r--r--tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs22
-rw-r--r--tests/ui/dynamically-sized-types/dst-tuple.rs119
-rw-r--r--tests/ui/error-codes/E0275.rs1
-rw-r--r--tests/ui/error-codes/E0275.stderr4
-rw-r--r--tests/ui/error-codes/E0462.stderr2
-rw-r--r--tests/ui/error-codes/E0464.stderr6
-rw-r--r--tests/ui/error-codes/E0523.stderr6
-rw-r--r--tests/ui/extern/issue-36122-accessing-externed-dst.stderr1
-rw-r--r--tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr11
-rw-r--r--tests/ui/feature-gates/feature-gate-min-generic-const-args.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr15
-rw-r--r--tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-where_clause_attrs.a.stderr883
-rw-r--r--tests/ui/feature-gates/feature-gate-where_clause_attrs.b.stderr883
-rw-r--r--tests/ui/feature-gates/feature-gate-where_clause_attrs.rs162
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr14
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr14
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr42
-rw-r--r--tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr2
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs1
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr12
-rw-r--r--tests/ui/impl-trait/unsize_tuple.rs15
-rw-r--r--tests/ui/implied-bounds/from-trait-impl.rs2
-rw-r--r--tests/ui/implied-bounds/from-trait-impl.stderr27
-rw-r--r--tests/ui/implied-bounds/normalization-nested.lifetime.stderr10
-rw-r--r--tests/ui/implied-bounds/normalization-nested.rs5
-rw-r--r--tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr34
-rw-r--r--tests/ui/implied-bounds/normalization-placeholder-leak.rs4
-rw-r--r--tests/ui/implied-bounds/sod_service_chain.rs8
-rw-r--r--tests/ui/implied-bounds/sod_service_chain.stderr76
-rw-r--r--tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs3
-rw-r--r--tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr10
-rw-r--r--tests/ui/infinite/infinite-instantiation.rs2
-rw-r--r--tests/ui/infinite/infinite-instantiation.stderr6
-rw-r--r--tests/ui/invalid-compile-flags/print-without-arg.stderr2
-rw-r--r--tests/ui/issues/issue-13497.rs1
-rw-r--r--tests/ui/issues/issue-13497.stderr14
-rw-r--r--tests/ui/issues/issue-20413.rs1
-rw-r--r--tests/ui/issues/issue-20413.stderr18
-rw-r--r--tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs2
-rw-r--r--tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr6
-rw-r--r--tests/ui/issues/issue-54410.stderr1
-rw-r--r--tests/ui/issues/issue-67552.rs2
-rw-r--r--tests/ui/issues/issue-67552.stderr6
-rw-r--r--tests/ui/issues/issue-8727.rs2
-rw-r--r--tests/ui/issues/issue-8727.stderr8
-rw-r--r--tests/ui/json/json-multiple.stderr2
-rw-r--r--tests/ui/json/json-options.stderr2
-rw-r--r--tests/ui/layout/issue-84108.stderr18
-rw-r--r--tests/ui/lifetimes/issue-26638.rs1
-rw-r--r--tests/ui/lifetimes/issue-26638.stderr17
-rw-r--r--tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs37
-rw-r--r--tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs28
-rw-r--r--tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs29
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr13
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr)2
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs9
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs)0
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr (renamed from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr)0
-rw-r--r--tests/ui/lint/removed-lints/README.md4
-rw-r--r--tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.rs5
-rw-r--r--tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.stderr10
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.rs2
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.stderr8
-rw-r--r--tests/ui/parser/bounds-lifetime-where.rs2
-rw-r--r--tests/ui/parser/bounds-lifetime-where.stderr4
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr2
-rw-r--r--tests/ui/parser/ranges-precedence.rs28
-rw-r--r--tests/ui/recursion/issue-23122-2.rs1
-rw-r--r--tests/ui/recursion/issue-23122-2.stderr4
-rw-r--r--tests/ui/recursion/issue-83150.rs3
-rw-r--r--tests/ui/recursion/issue-83150.stderr8
-rw-r--r--tests/ui/recursion/recursion.rs2
-rw-r--r--tests/ui/recursion/recursion.stderr6
-rw-r--r--tests/ui/regions/issue-102374.rs1
-rw-r--r--tests/ui/regions/issue-102374.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs5
-rw-r--r--tests/ui/rmeta/emit-artifact-notifications.stderr2
-rw-r--r--tests/ui/simd/intrinsic/generic-gather.rs52
-rw-r--r--tests/ui/simd/intrinsic/generic-gather.stderr39
-rw-r--r--tests/ui/simd/intrinsic/generic-select.rs4
-rw-r--r--tests/ui/simd/intrinsic/generic-select.stderr8
-rw-r--r--tests/ui/static/issue-24446.stderr1
-rw-r--r--tests/ui/statics/unsized_type2.stderr1
-rw-r--r--tests/ui/stats/input-stats.stderr28
-rw-r--r--tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs2
-rw-r--r--tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr13
-rw-r--r--tests/ui/structs/default-field-values/failures.rs4
-rw-r--r--tests/ui/structs/default-field-values/failures.stderr17
-rw-r--r--tests/ui/structs/default-field-values/field-references-param.rs29
-rw-r--r--tests/ui/structs/default-field-values/post-mono.direct.stderr23
-rw-r--r--tests/ui/structs/default-field-values/post-mono.indirect.stderr29
-rw-r--r--tests/ui/structs/default-field-values/post-mono.rs23
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs2
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr40
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.rs2
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.stderr18
-rw-r--r--tests/ui/suggestions/missing-lt-for-hrtb.rs2
-rw-r--r--tests/ui/suggestions/missing-lt-for-hrtb.stderr24
-rw-r--r--tests/ui/target_modifiers/auxiliary/default_reg_struct_return.rs21
-rw-r--r--tests/ui/target_modifiers/auxiliary/wrong_regparm.rs21
-rw-r--r--tests/ui/target_modifiers/auxiliary/wrong_regparm_and_ret.rs21
-rw-r--r--tests/ui/target_modifiers/defaults_check.error.stderr4
-rw-r--r--tests/ui/target_modifiers/defaults_check.rs27
-rw-r--r--tests/ui/target_modifiers/incompatible_regparm.error_generated.stderr4
-rw-r--r--tests/ui/target_modifiers/incompatible_regparm.rs23
-rw-r--r--tests/ui/target_modifiers/two_flags.rs22
-rw-r--r--tests/ui/target_modifiers/two_flags.unknown_allowed.stderr4
-rw-r--r--tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr1
-rw-r--r--tests/ui/traits/next-solver/unsize-good.rs6
-rw-r--r--tests/ui/traits/on_unimplemented_long_types.rs2
-rw-r--r--tests/ui/traits/on_unimplemented_long_types.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.stderr50
-rw-r--r--tests/ui/type_length_limit.rs3
-rw-r--r--tests/ui/type_length_limit.stderr4
-rw-r--r--tests/ui/unpretty/deprecated-attr.rs17
-rw-r--r--tests/ui/unpretty/deprecated-attr.stdout21
-rw-r--r--tests/ui/unpretty/diagnostic-attr.rs13
-rw-r--r--tests/ui/unpretty/diagnostic-attr.stdout16
-rw-r--r--tests/ui/unsafe-binders/type-mismatch.rs9
-rw-r--r--tests/ui/unsafe-binders/type-mismatch.stderr34
-rw-r--r--tests/ui/unsized-locals/rust-call.rs12
-rw-r--r--tests/ui/unsized-locals/rust-call.stderr13
-rw-r--r--tests/ui/unsized-locals/unsized-exprs-rpass.rs6
-rw-r--r--tests/ui/unsized-locals/unsized-exprs.rs7
-rw-r--r--tests/ui/unsized-locals/unsized-exprs.stderr16
-rw-r--r--tests/ui/unsized-locals/unsized-exprs2.rs5
-rw-r--r--tests/ui/unsized-locals/unsized-exprs2.stderr2
-rw-r--r--tests/ui/unsized/unsized-tuple-impls.rs21
-rw-r--r--tests/ui/wf/wf-normalization-sized.next.stderr20
-rw-r--r--tests/ui/where-clauses/cfg_attribute.a.stderr288
-rw-r--r--tests/ui/where-clauses/cfg_attribute.b.stderr288
-rw-r--r--tests/ui/where-clauses/cfg_attribute.rs183
-rw-r--r--tests/ui/where-clauses/unsupported_attribute.rs36
-rw-r--r--tests/ui/where-clauses/unsupported_attribute.stderr158
-rw-r--r--triagebot.toml18
-rwxr-xr-xx8
883 files changed, 20462 insertions, 17842 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 949932b8e2a..f166e0c0b41 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,8 +1,8 @@
 # This file defines our primary CI workflow that runs on pull requests
 # and also on pushes to special branches (auto, try).
 #
-# The actual definition of the executed jobs is calculated by a Python
-# script located at src/ci/github-actions/ci.py, which
+# The actual definition of the executed jobs is calculated by the
+# `src/ci/citool` crate, which
 # uses job definition data from src/ci/github-actions/jobs.yml.
 # You should primarily modify the `jobs.yml` file if you want to modify
 # what jobs are executed in CI.
@@ -56,7 +56,10 @@ jobs:
       - name: Calculate the CI job matrix
         env:
           COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
-        run: python3 src/ci/github-actions/ci.py calculate-job-matrix >> $GITHUB_OUTPUT
+        run: |
+          cd src/ci/citool
+          CARGO_INCREMENTAL=0 cargo test
+          CARGO_INCREMENTAL=0 cargo run calculate-job-matrix >> $GITHUB_OUTPUT
         id: jobs
   job:
     name: ${{ matrix.full_name }}
@@ -179,19 +182,12 @@ jobs:
       - name: show the current environment
         run: src/ci/scripts/dump-environment.sh
 
-      # Temporary fix to unblock CI
-      # Remove the latest Windows SDK for 32-bit Windows MSVC builds.
-      # See issue https://github.com/rust-lang/rust/issues/137733 for more details.
-      - name: Remove Windows SDK 10.0.26100.0
-        shell: powershell
-        if: ${{ matrix.name == 'i686-msvc-1' || matrix.name == 'i686-msvc-2' || matrix.name == 'dist-i686-msvc' }}
+      # Pre-build citool before the following step uninstalls rustup
+      # Build it into the build directory, to avoid modifying sources
+      - name: build citool
         run: |
-          $kits = (Get-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots').KitsRoot10
-          $sdk_version = "10.0.26100.0"
-
-          foreach ($kind in 'Bin', 'Lib', 'Include') {
-            Remove-Item -Force -Recurse $kits\$kind\$sdk_version -ErrorAction Continue
-          }
+          cd src/ci/citool
+          CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build
 
       - name: run the build
         # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
@@ -229,16 +225,22 @@ jobs:
         # erroring about invalid credentials instead.
         if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1'
 
+      - name: postprocess metrics into the summary
+        run: |
+          if [ -f build/metrics.json ]; then
+            ./build/citool/debug/citool postprocess-metrics build/metrics.json ${GITHUB_STEP_SUMMARY}
+          elif [ -f obj/build/metrics.json ]; then
+            ./build/citool/debug/citool postprocess-metrics obj/build/metrics.json ${GITHUB_STEP_SUMMARY}
+          else
+            echo "No metrics.json found"
+          fi
+
       - name: upload job metrics to DataDog
         if: needs.calculate_matrix.outputs.run_type != 'pr'
         env:
-          DATADOG_SITE: datadoghq.com
           DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
           DD_GITHUB_JOB_NAME: ${{ matrix.full_name }}
-        run: |
-          cd src/ci
-          npm ci
-          python3 scripts/upload-build-metrics.py ../../build/cpu-usage.csv
+        run: ./build/citool/debug/citool upload-build-metrics build/cpu-usage.csv
 
   # This job isused to tell bors the final status of the build, as there is no practical way to detect
   # when a workflow is successful listening to webhooks only in our current bors implementation (homu).
diff --git a/.mailmap b/.mailmap
index eb6a9fcabca..a791daa681d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -292,6 +292,9 @@ James Hinshelwood <jameshinshelwood1@gmail.com> <james.hinshelwood@bigpayme.com>
 James Miller <bladeon@gmail.com> <james@aatch.net>
 James Perry <james.austin.perry@gmail.com>
 James Sanderson <zofrex@gmail.com>
+Jana Dönszelmann <jana@donsz.nl>
+Jana Dönszelmann <jana@donsz.nl> <jonathan@donsz.nl>
+Jana Dönszelmann <jana@donsz.nl> <jonabent@gmail.com>
 Jan-Erik Rediger <janerik@fnordig.de> <badboy@archlinux.us>
 Jaro Fietz <jaro.fietz@gmx.de>
 Jason Fager <jfager@gmail.com>
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a5ddff595f5..e155e253784 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,7 +18,7 @@ For submodules, changes need to be made against the repository corresponding the
 submodule, and not the main `rust-lang/rust` repository.
 
 For subtrees, prefer sending a PR against the subtree's repository if it does
-not need to be made against the main `rust-lang/rust` repostory (e.g. a
+not need to be made against the main `rust-lang/rust` repository (e.g. a
 rustc-dev-guide change that does not accompany a compiler change).
 
 ## About the [rustc-dev-guide]
diff --git a/INSTALL.md b/INSTALL.md
index 74fcc58348b..a46d3d70093 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -210,9 +210,13 @@ itself back on after some time).
 
 ### MSVC
 
-MSVC builds of Rust additionally require an installation of Visual Studio 2017
-(or later) so `rustc` can use its linker. The simplest way is to get
-[Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload.
+MSVC builds of Rust additionally requires an installation of:
+
+- Visual Studio 2022 (or later) build tools so `rustc` can use its linker. Older
+  Visual Studio versions such as 2019 *may* work but aren't actively tested.
+- A recent Windows 10 or 11 SDK.
+
+The simplest way is to get [Visual Studio], check the "C++ build tools".
 
 [Visual Studio]: https://visualstudio.microsoft.com/downloads/
 
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index 543c2f8ab12..4d70afd4e0b 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -191,6 +191,17 @@ impl StableOrd for ExternAbi {
 }
 
 impl ExternAbi {
+    /// An ABI "like Rust"
+    ///
+    /// These ABIs are fully controlled by the Rust compiler, which means they
+    /// - support unwinding with `-Cpanic=unwind`, unlike `extern "C"`
+    /// - often diverge from the C ABI
+    /// - are subject to change between compiler versions
+    pub fn is_rustic_abi(self) -> bool {
+        use ExternAbi::*;
+        matches!(self, Rust | RustCall | RustIntrinsic | RustCold)
+    }
+
     pub fn supports_varargs(self) -> bool {
         // * C and Cdecl obviously support varargs.
         // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 5c44fda2262..fb6b36e1a09 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -124,10 +124,19 @@ impl Path {
         self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
     }
 
-    /// If this path is a single identifier with no arguments, does not ensure
-    /// that the path resolves to a const param, the caller should check this.
-    pub fn is_potential_trivial_const_arg(&self) -> bool {
-        matches!(self.segments[..], [PathSegment { args: None, .. }])
+    /// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_
+    /// be represented without an anon const in the HIR.
+    ///
+    /// If `allow_mgca_arg` is true (as should be the case in most situations when
+    /// `#![feature(min_generic_const_args)]` is enabled), then this always returns true
+    /// because all paths are valid.
+    ///
+    /// Otherwise, it returns true iff the path has exactly one segment, and it has no generic args
+    /// (i.e., it is _potentially_ a const parameter).
+    #[tracing::instrument(level = "debug", ret)]
+    pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
+        allow_mgca_arg
+            || self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
     }
 }
 
@@ -417,9 +426,11 @@ impl WhereClause {
 /// A single predicate in a where-clause.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct WherePredicate {
+    pub attrs: AttrVec,
     pub kind: WherePredicateKind,
     pub id: NodeId,
     pub span: Span,
+    pub is_placeholder: bool,
 }
 
 /// Predicate kind in where-clause.
@@ -1206,22 +1217,31 @@ pub struct Expr {
 }
 
 impl Expr {
-    /// Could this expr be either `N`, or `{ N }`, where `N` is a const parameter.
+    /// Check if this expression is potentially a trivial const arg, i.e., one that can _potentially_
+    /// be represented without an anon const in the HIR.
+    ///
+    /// This will unwrap at most one block level (curly braces). After that, if the expression
+    /// is a path, it mostly dispatches to [`Path::is_potential_trivial_const_arg`].
+    /// See there for more info about `allow_mgca_arg`.
     ///
-    /// If this is not the case, name resolution does not resolve `N` when using
-    /// `min_const_generics` as more complex expressions are not supported.
+    /// The only additional thing to note is that when `allow_mgca_arg` is false, this function
+    /// will only allow paths with no qself, before dispatching to the `Path` function of
+    /// the same name.
     ///
-    /// Does not ensure that the path resolves to a const param, the caller should check this.
+    /// Does not ensure that the path resolves to a const param/item, the caller should check this.
     /// This also does not consider macros, so it's only correct after macro-expansion.
-    pub fn is_potential_trivial_const_arg(&self) -> bool {
+    pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
         let this = self.maybe_unwrap_block();
-
-        if let ExprKind::Path(None, path) = &this.kind
-            && path.is_potential_trivial_const_arg()
-        {
-            true
+        if allow_mgca_arg {
+            matches!(this.kind, ExprKind::Path(..))
         } else {
-            false
+            if let ExprKind::Path(None, path) = &this.kind
+                && path.is_potential_trivial_const_arg(allow_mgca_arg)
+            {
+                true
+            } else {
+                false
+            }
         }
     }
 
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 4a2d9559385..a37c0f92b12 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -11,7 +11,7 @@ use crate::tokenstream::LazyAttrTokenStream;
 use crate::{
     Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
     FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
-    Ty, Variant, Visibility,
+    Ty, Variant, Visibility, WherePredicate,
 };
 
 /// A utility trait to reduce boilerplate.
@@ -79,6 +79,7 @@ impl_has_node_id!(
     Stmt,
     Ty,
     Variant,
+    WherePredicate,
 );
 
 impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
@@ -127,7 +128,16 @@ macro_rules! impl_has_tokens_none {
 }
 
 impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
-impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
+impl_has_tokens_none!(
+    Arm,
+    ExprField,
+    FieldDef,
+    GenericParam,
+    Param,
+    PatField,
+    Variant,
+    WherePredicate
+);
 
 impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
     fn tokens(&self) -> Option<&LazyAttrTokenStream> {
@@ -279,6 +289,7 @@ impl_has_attrs!(
     Param,
     PatField,
     Variant,
+    WherePredicate,
 );
 impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9be364e320b..f14646b5a99 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -338,8 +338,11 @@ pub trait MutVisitor: Sized {
         walk_where_clause(self, where_clause);
     }
 
-    fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) {
-        walk_where_predicate(self, where_predicate)
+    fn flat_map_where_predicate(
+        &mut self,
+        where_predicate: WherePredicate,
+    ) -> SmallVec<[WherePredicate; 1]> {
+        walk_flat_map_where_predicate(self, where_predicate)
     }
 
     fn visit_where_predicate_kind(&mut self, kind: &mut WherePredicateKind) {
@@ -1097,15 +1100,20 @@ fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWh
 
 fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) {
     let WhereClause { has_where_token: _, predicates, span } = wc;
-    visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
+    predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate));
     vis.visit_span(span);
 }
 
-pub fn walk_where_predicate<T: MutVisitor>(vis: &mut T, pred: &mut WherePredicate) {
-    let WherePredicate { kind, id, span } = pred;
+pub fn walk_flat_map_where_predicate<T: MutVisitor>(
+    vis: &mut T,
+    mut pred: WherePredicate,
+) -> SmallVec<[WherePredicate; 1]> {
+    let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = &mut pred;
     vis.visit_id(id);
+    visit_attrs(vis, attrs);
     vis.visit_where_predicate_kind(kind);
     vis.visit_span(span);
+    smallvec![pred]
 }
 
 pub fn walk_where_predicate_kind<T: MutVisitor>(vis: &mut T, kind: &mut WherePredicateKind) {
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 6cd0e15c557..ff1edad725a 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -2,7 +2,6 @@ use std::borrow::Cow;
 use std::fmt;
 use std::sync::Arc;
 
-pub use BinOpToken::*;
 pub use LitKind::*;
 pub use Nonterminal::*;
 pub use NtExprKind::*;
@@ -26,21 +25,6 @@ pub enum CommentKind {
     Block,
 }
 
-#[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
-#[derive(HashStable_Generic)]
-pub enum BinOpToken {
-    Plus,
-    Minus,
-    Star,
-    Slash,
-    Percent,
-    Caret,
-    And,
-    Or,
-    Shl,
-    Shr,
-}
-
 // This type must not implement `Hash` due to the unusual `PartialEq` impl below.
 #[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum InvisibleOrigin {
@@ -376,11 +360,49 @@ pub enum TokenKind {
     /// `||`
     OrOr,
     /// `!`
-    Not,
+    Bang,
     /// `~`
     Tilde,
-    BinOp(BinOpToken),
-    BinOpEq(BinOpToken),
+    // `+`
+    Plus,
+    // `-`
+    Minus,
+    // `*`
+    Star,
+    // `/`
+    Slash,
+    // `%`
+    Percent,
+    // `^`
+    Caret,
+    // `&`
+    And,
+    // `|`
+    Or,
+    // `<<`
+    Shl,
+    // `>>`
+    Shr,
+    // `+=`
+    PlusEq,
+    // `-=`
+    MinusEq,
+    // `*=`
+    StarEq,
+    // `/=`
+    SlashEq,
+    // `%=`
+    PercentEq,
+    // `^=`
+    CaretEq,
+    // `&=`
+    AndEq,
+    // `|=`
+    OrEq,
+    // `<<=`
+    ShlEq,
+    // `>>=`
+    ShrEq,
 
     /* Structural symbols */
     /// `@`
@@ -500,31 +522,31 @@ impl TokenKind {
         Some(match (self, n) {
             (Le, 1) => (Lt, Eq),
             (EqEq, 1) => (Eq, Eq),
-            (Ne, 1) => (Not, Eq),
+            (Ne, 1) => (Bang, Eq),
             (Ge, 1) => (Gt, Eq),
-            (AndAnd, 1) => (BinOp(And), BinOp(And)),
-            (OrOr, 1) => (BinOp(Or), BinOp(Or)),
-            (BinOp(Shl), 1) => (Lt, Lt),
-            (BinOp(Shr), 1) => (Gt, Gt),
-            (BinOpEq(Plus), 1) => (BinOp(Plus), Eq),
-            (BinOpEq(Minus), 1) => (BinOp(Minus), Eq),
-            (BinOpEq(Star), 1) => (BinOp(Star), Eq),
-            (BinOpEq(Slash), 1) => (BinOp(Slash), Eq),
-            (BinOpEq(Percent), 1) => (BinOp(Percent), Eq),
-            (BinOpEq(Caret), 1) => (BinOp(Caret), Eq),
-            (BinOpEq(And), 1) => (BinOp(And), Eq),
-            (BinOpEq(Or), 1) => (BinOp(Or), Eq),
-            (BinOpEq(Shl), 1) => (Lt, Le),         // `<` + `<=`
-            (BinOpEq(Shl), 2) => (BinOp(Shl), Eq), // `<<` + `=`
-            (BinOpEq(Shr), 1) => (Gt, Ge),         // `>` + `>=`
-            (BinOpEq(Shr), 2) => (BinOp(Shr), Eq), // `>>` + `=`
+            (AndAnd, 1) => (And, And),
+            (OrOr, 1) => (Or, Or),
+            (Shl, 1) => (Lt, Lt),
+            (Shr, 1) => (Gt, Gt),
+            (PlusEq, 1) => (Plus, Eq),
+            (MinusEq, 1) => (Minus, Eq),
+            (StarEq, 1) => (Star, Eq),
+            (SlashEq, 1) => (Slash, Eq),
+            (PercentEq, 1) => (Percent, Eq),
+            (CaretEq, 1) => (Caret, Eq),
+            (AndEq, 1) => (And, Eq),
+            (OrEq, 1) => (Or, Eq),
+            (ShlEq, 1) => (Lt, Le),  // `<` + `<=`
+            (ShlEq, 2) => (Shl, Eq), // `<<` + `=`
+            (ShrEq, 1) => (Gt, Ge),  // `>` + `>=`
+            (ShrEq, 2) => (Shr, Eq), // `>>` + `=`
             (DotDot, 1) => (Dot, Dot),
             (DotDotDot, 1) => (Dot, DotDot), // `.` + `..`
             (DotDotDot, 2) => (DotDot, Dot), // `..` + `.`
             (DotDotEq, 2) => (DotDot, Eq),
             (PathSep, 1) => (Colon, Colon),
-            (RArrow, 1) => (BinOp(Minus), Gt),
-            (LArrow, 1) => (Lt, BinOp(Minus)),
+            (RArrow, 1) => (Minus, Gt),
+            (LArrow, 1) => (Lt, Minus),
             (FatArrow, 1) => (Eq, Gt),
             _ => return None,
         })
@@ -543,7 +565,7 @@ impl TokenKind {
     }
 
     pub fn should_end_const_arg(&self) -> bool {
-        matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr))
+        matches!(self, Gt | Ge | Shr | ShrEq)
     }
 }
 
@@ -582,11 +604,11 @@ impl Token {
 
     pub fn is_punct(&self) -> bool {
         match self.kind {
-            Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
-            | BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
-            | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => {
-                true
-            }
+            Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Bang | Tilde | Plus | Minus
+            | Star | Slash | Percent | Caret | And | Or | Shl | Shr | PlusEq | MinusEq | StarEq
+            | SlashEq | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | Dot | DotDot
+            | DotDotDot | DotDotEq | Comma | Semi | Colon | PathSep | RArrow | LArrow
+            | FatArrow | Pound | Dollar | Question | SingleQuote => true,
 
             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
             | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Interpolated(..) | Eof => false,
@@ -594,7 +616,7 @@ impl Token {
     }
 
     pub fn is_like_plus(&self) -> bool {
-        matches!(self.kind, BinOp(Plus) | BinOpEq(Plus))
+        matches!(self.kind, Plus | PlusEq)
     }
 
     /// Returns `true` if the token can appear at the start of an expression.
@@ -608,15 +630,15 @@ impl Token {
                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
             OpenDelim(Parenthesis | Brace | Bracket) | // tuple, array or block
             Literal(..)                       | // literal
-            Not                               | // operator not
-            BinOp(Minus)                      | // unary minus
-            BinOp(Star)                       | // dereference
-            BinOp(Or) | OrOr                  | // closure
-            BinOp(And)                        | // reference
+            Bang                              | // operator not
+            Minus                             | // unary minus
+            Star                              | // dereference
+            Or | OrOr                         | // closure
+            And                               | // reference
             AndAnd                            | // double reference
             // DotDotDot is no longer supported, but we need some way to display the error
             DotDot | DotDotDot | DotDotEq     | // range notation
-            Lt | BinOp(Shl)                   | // associated path
+            Lt | Shl                          | // associated path
             PathSep                           | // global path
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
@@ -645,17 +667,16 @@ impl Token {
             Ident(..) | NtIdent(..) |
             OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
             OpenDelim(Delimiter::Bracket) |      // slice pattern
-            BinOp(And) |                  // reference
-            BinOp(Minus) |                // negative literal
-            AndAnd |                      // double reference
-            Literal(_) |                  // literal
-            DotDot |                      // range pattern (future compat)
-            DotDotDot |                   // range pattern (future compat)
-            PathSep |                     // path
-            Lt |                          // path (UFCS constant)
-            BinOp(Shl) => true,           // path (double UFCS)
-            // leading vert `|` or-pattern
-            BinOp(Or) => matches!(pat_kind, PatWithOr),
+            And |                                // reference
+            Minus |                              // negative literal
+            AndAnd |                             // double reference
+            Literal(_) |                         // literal
+            DotDot |                             // range pattern (future compat)
+            DotDotDot |                          // range pattern (future compat)
+            PathSep |                            // path
+            Lt |                                 // path (UFCS constant)
+            Shl => true,                         // path (double UFCS)
+            Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern
             Interpolated(nt) =>
                 matches!(&**nt,
                     | NtExpr(..)
@@ -676,18 +697,18 @@ impl Token {
     /// Returns `true` if the token can appear at the start of a type.
     pub fn can_begin_type(&self) -> bool {
         match self.uninterpolate().kind {
-            Ident(name, is_raw)        =>
+            Ident(name, is_raw) =>
                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
             OpenDelim(Delimiter::Parenthesis) | // tuple
             OpenDelim(Delimiter::Bracket)     | // array
-            Not                         | // never
-            BinOp(Star)                 | // raw pointer
-            BinOp(And)                  | // reference
-            AndAnd                      | // double reference
-            Question                    | // maybe bound in trait object
-            Lifetime(..)                | // lifetime bound in trait object
-            Lt | BinOp(Shl)             | // associated path
-            PathSep                      => true, // global path
+            Bang                              | // never
+            Star                              | // raw pointer
+            And                               | // reference
+            AndAnd                            | // double reference
+            Question                          | // maybe bound in trait object
+            Lifetime(..)                      | // lifetime bound in trait object
+            Lt | Shl                          | // associated path
+            PathSep => true,                    // global path
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Ty { .. } |
                 MetaVarKind::Path
@@ -701,7 +722,7 @@ impl Token {
     /// Returns `true` if the token can appear at the start of a const param.
     pub fn can_begin_const_arg(&self) -> bool {
         match self.kind {
-            OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true,
+            OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true,
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
             Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
@@ -750,7 +771,7 @@ impl Token {
     /// Keep this in sync with and `Lit::from_token`, excluding unary negation.
     pub fn can_begin_literal_maybe_minus(&self) -> bool {
         match self.uninterpolate().kind {
-            Literal(..) | BinOp(Minus) => true,
+            Literal(..) | Minus => true,
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
             Interpolated(ref nt) => match &**nt {
                 NtLiteral(_) => true,
@@ -875,7 +896,7 @@ impl Token {
     }
 
     pub fn is_qpath_start(&self) -> bool {
-        self == &Lt || self == &BinOp(Shl)
+        self == &Lt || self == &Shl
     }
 
     pub fn is_path_start(&self) -> bool {
@@ -967,59 +988,82 @@ impl Token {
     }
 
     pub fn glue(&self, joint: &Token) -> Option<Token> {
-        let kind = match self.kind {
-            Eq => match joint.kind {
-                Eq => EqEq,
-                Gt => FatArrow,
-                _ => return None,
-            },
-            Lt => match joint.kind {
-                Eq => Le,
-                Lt => BinOp(Shl),
-                Le => BinOpEq(Shl),
-                BinOp(Minus) => LArrow,
-                _ => return None,
-            },
-            Gt => match joint.kind {
-                Eq => Ge,
-                Gt => BinOp(Shr),
-                Ge => BinOpEq(Shr),
-                _ => return None,
-            },
-            Not => match joint.kind {
-                Eq => Ne,
-                _ => return None,
-            },
-            BinOp(op) => match joint.kind {
-                Eq => BinOpEq(op),
-                BinOp(And) if op == And => AndAnd,
-                BinOp(Or) if op == Or => OrOr,
-                Gt if op == Minus => RArrow,
-                _ => return None,
-            },
-            Dot => match joint.kind {
-                Dot => DotDot,
-                DotDot => DotDotDot,
-                _ => return None,
-            },
-            DotDot => match joint.kind {
-                Dot => DotDotDot,
-                Eq => DotDotEq,
-                _ => return None,
-            },
-            Colon => match joint.kind {
-                Colon => PathSep,
-                _ => return None,
-            },
-            SingleQuote => match joint.kind {
-                Ident(name, is_raw) => Lifetime(Symbol::intern(&format!("'{name}")), is_raw),
-                _ => return None,
-            },
+        let kind = match (&self.kind, &joint.kind) {
+            (Eq, Eq) => EqEq,
+            (Eq, Gt) => FatArrow,
+            (Eq, _) => return None,
+
+            (Lt, Eq) => Le,
+            (Lt, Lt) => Shl,
+            (Lt, Le) => ShlEq,
+            (Lt, Minus) => LArrow,
+            (Lt, _) => return None,
+
+            (Gt, Eq) => Ge,
+            (Gt, Gt) => Shr,
+            (Gt, Ge) => ShrEq,
+            (Gt, _) => return None,
+
+            (Bang, Eq) => Ne,
+            (Bang, _) => return None,
+
+            (Plus, Eq) => PlusEq,
+            (Plus, _) => return None,
+
+            (Minus, Eq) => MinusEq,
+            (Minus, Gt) => RArrow,
+            (Minus, _) => return None,
 
-            Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
-            | DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar
-            | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..)
-            | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof => {
+            (Star, Eq) => StarEq,
+            (Star, _) => return None,
+
+            (Slash, Eq) => SlashEq,
+            (Slash, _) => return None,
+
+            (Percent, Eq) => PercentEq,
+            (Percent, _) => return None,
+
+            (Caret, Eq) => CaretEq,
+            (Caret, _) => return None,
+
+            (And, Eq) => AndEq,
+            (And, And) => AndAnd,
+            (And, _) => return None,
+
+            (Or, Eq) => OrEq,
+            (Or, Or) => OrOr,
+            (Or, _) => return None,
+
+            (Shl, Eq) => ShlEq,
+            (Shl, _) => return None,
+
+            (Shr, Eq) => ShrEq,
+            (Shr, _) => return None,
+
+            (Dot, Dot) => DotDot,
+            (Dot, DotDot) => DotDotDot,
+            (Dot, _) => return None,
+
+            (DotDot, Dot) => DotDotDot,
+            (DotDot, Eq) => DotDotEq,
+            (DotDot, _) => return None,
+
+            (Colon, Colon) => PathSep,
+            (Colon, _) => return None,
+
+            (SingleQuote, Ident(name, is_raw)) => {
+                Lifetime(Symbol::intern(&format!("'{name}")), *is_raw)
+            }
+            (SingleQuote, _) => return None,
+
+            (
+                Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | PlusEq | MinusEq | StarEq | SlashEq
+                | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq
+                | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
+                | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..)
+                | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof,
+                _,
+            ) => {
                 return None;
             }
         };
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 49ae8cc78fc..b9b20cf9376 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -651,7 +651,7 @@ impl TokenStream {
             if attr_style == AttrStyle::Inner {
                 vec![
                     TokenTree::token_joint(token::Pound, span),
-                    TokenTree::token_joint_hidden(token::Not, span),
+                    TokenTree::token_joint_hidden(token::Bang, span),
                     body,
                 ]
             } else {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 69454967eed..98b1fc52ed7 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -1,7 +1,7 @@
 use rustc_span::kw;
 
 use crate::ast::{self, BinOpKind, RangeLimits};
-use crate::token::{self, BinOpToken, Token};
+use crate::token::{self, Token};
 
 /// Associative operator.
 #[derive(Copy, Clone, PartialEq, Debug)]
@@ -34,26 +34,26 @@ impl AssocOp {
         use AssocOp::*;
         match t.kind {
             token::Eq => Some(Assign),
-            token::BinOp(BinOpToken::Plus) => Some(Binary(BinOpKind::Add)),
-            token::BinOp(BinOpToken::Minus) => Some(Binary(BinOpKind::Sub)),
-            token::BinOp(BinOpToken::Star) => Some(Binary(BinOpKind::Mul)),
-            token::BinOp(BinOpToken::Slash) => Some(Binary(BinOpKind::Div)),
-            token::BinOp(BinOpToken::Percent) => Some(Binary(BinOpKind::Rem)),
-            token::BinOp(BinOpToken::Caret) => Some(Binary(BinOpKind::BitXor)),
-            token::BinOp(BinOpToken::And) => Some(Binary(BinOpKind::BitAnd)),
-            token::BinOp(BinOpToken::Or) => Some(Binary(BinOpKind::BitOr)),
-            token::BinOp(BinOpToken::Shl) => Some(Binary(BinOpKind::Shl)),
-            token::BinOp(BinOpToken::Shr) => Some(Binary(BinOpKind::Shr)),
-            token::BinOpEq(BinOpToken::Plus) => Some(AssignOp(BinOpKind::Add)),
-            token::BinOpEq(BinOpToken::Minus) => Some(AssignOp(BinOpKind::Sub)),
-            token::BinOpEq(BinOpToken::Star) => Some(AssignOp(BinOpKind::Mul)),
-            token::BinOpEq(BinOpToken::Slash) => Some(AssignOp(BinOpKind::Div)),
-            token::BinOpEq(BinOpToken::Percent) => Some(AssignOp(BinOpKind::Rem)),
-            token::BinOpEq(BinOpToken::Caret) => Some(AssignOp(BinOpKind::BitXor)),
-            token::BinOpEq(BinOpToken::And) => Some(AssignOp(BinOpKind::BitAnd)),
-            token::BinOpEq(BinOpToken::Or) => Some(AssignOp(BinOpKind::BitOr)),
-            token::BinOpEq(BinOpToken::Shl) => Some(AssignOp(BinOpKind::Shl)),
-            token::BinOpEq(BinOpToken::Shr) => Some(AssignOp(BinOpKind::Shr)),
+            token::Plus => Some(Binary(BinOpKind::Add)),
+            token::Minus => Some(Binary(BinOpKind::Sub)),
+            token::Star => Some(Binary(BinOpKind::Mul)),
+            token::Slash => Some(Binary(BinOpKind::Div)),
+            token::Percent => Some(Binary(BinOpKind::Rem)),
+            token::Caret => Some(Binary(BinOpKind::BitXor)),
+            token::And => Some(Binary(BinOpKind::BitAnd)),
+            token::Or => Some(Binary(BinOpKind::BitOr)),
+            token::Shl => Some(Binary(BinOpKind::Shl)),
+            token::Shr => Some(Binary(BinOpKind::Shr)),
+            token::PlusEq => Some(AssignOp(BinOpKind::Add)),
+            token::MinusEq => Some(AssignOp(BinOpKind::Sub)),
+            token::StarEq => Some(AssignOp(BinOpKind::Mul)),
+            token::SlashEq => Some(AssignOp(BinOpKind::Div)),
+            token::PercentEq => Some(AssignOp(BinOpKind::Rem)),
+            token::CaretEq => Some(AssignOp(BinOpKind::BitXor)),
+            token::AndEq => Some(AssignOp(BinOpKind::BitAnd)),
+            token::OrEq => Some(AssignOp(BinOpKind::BitOr)),
+            token::ShlEq => Some(AssignOp(BinOpKind::Shl)),
+            token::ShrEq => Some(AssignOp(BinOpKind::Shr)),
             token::Lt => Some(Binary(BinOpKind::Lt)),
             token::Le => Some(Binary(BinOpKind::Le)),
             token::Ge => Some(Binary(BinOpKind::Ge)),
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 1cb32b56875..37139e664f3 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -833,7 +833,8 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(
     visitor: &mut V,
     predicate: &'a WherePredicate,
 ) -> V::Result {
-    let WherePredicate { kind, id: _, span: _ } = predicate;
+    let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
+    walk_list!(visitor, visit_attribute, attrs);
     visitor.visit_where_predicate_kind(kind)
 }
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 15802101f71..5e89321e6ec 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1728,6 +1728,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
         let hir_id = self.lower_node_id(pred.id);
         let span = self.lower_span(pred.span);
+        self.lower_attrs(hir_id, &pred.attrs, span);
         let kind = self.arena.alloc(match &pred.kind {
             WherePredicateKind::BoundPredicate(WhereBoundPredicate {
                 bound_generic_params,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 13edcc10c9e..c0188dde565 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1094,7 +1094,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             .and_then(|partial_res| partial_res.full_res())
                         {
                             if !res.matches_ns(Namespace::TypeNS)
-                                && path.is_potential_trivial_const_arg()
+                                && path.is_potential_trivial_const_arg(false)
                             {
                                 debug!(
                                     "lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -2061,8 +2061,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> &'hir hir::ConstArg<'hir> {
         let tcx = self.tcx;
 
-        // FIXME(min_generic_const_args): we only allow one-segment const paths for now
-        let ct_kind = if path.is_potential_trivial_const_arg()
+        let ct_kind = if path
+            .is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
             && (tcx.features().min_generic_const_args()
                 || matches!(res, Res::Def(DefKind::ConstParam, _)))
         {
@@ -2072,7 +2072,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 path,
                 ParamMode::Optional,
                 AllowReturnTypeNotation::No,
-                // FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
+                // FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
@@ -2136,19 +2136,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         let maybe_res =
             self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
-        // FIXME(min_generic_const_args): we only allow one-segment const paths for now
-        if let ExprKind::Path(None, path) = &expr.kind
-            && path.is_potential_trivial_const_arg()
+        if let ExprKind::Path(qself, path) = &expr.kind
+            && path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
             && (tcx.features().min_generic_const_args()
                 || matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
         {
             let qpath = self.lower_qpath(
                 expr.id,
-                &None,
+                qself,
                 path,
                 ParamMode::Optional,
                 AllowReturnTypeNotation::No,
-                // FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
+                // FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 0f80e49320e..de11fe770c5 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -503,6 +503,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(unsafe_binders, "unsafe binder types are experimental");
     gate_all!(contracts, "contracts are incomplete");
     gate_all!(contracts_internals, "contract internal machinery is for internal use only");
+    gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
 
     if !visitor.features.never_patterns() {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 44e956dc37f..d747237f76d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -11,9 +11,7 @@ use std::sync::Arc;
 
 use rustc_ast::attr::AttrIdGenerator;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{
-    self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind,
-};
+use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{Comment, CommentStyle};
@@ -319,7 +317,7 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
         (tt1, Tok(Token { kind: Comma | Semi | Dot, .. }, _)) if !is_punct(tt1) => false,
 
         // IDENT + `!`: `println!()`, but `if !x { ... }` needs a space after the `if`
-        (Tok(Token { kind: Ident(sym, is_raw), span }, _), Tok(Token { kind: Not, .. }, _))
+        (Tok(Token { kind: Ident(sym, is_raw), span }, _), Tok(Token { kind: Bang, .. }, _))
             if !Ident::new(*sym, *span).is_reserved() || matches!(is_raw, IdentIsRaw::Yes) =>
         {
             false
@@ -344,21 +342,6 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
     }
 }
 
-fn binop_to_string(op: BinOpToken) -> &'static str {
-    match op {
-        token::Plus => "+",
-        token::Minus => "-",
-        token::Star => "*",
-        token::Slash => "/",
-        token::Percent => "%",
-        token::Caret => "^",
-        token::And => "&",
-        token::Or => "|",
-        token::Shl => "<<",
-        token::Shr => ">>",
-    }
-}
-
 pub fn doc_comment_to_string(
     comment_kind: CommentKind,
     attr_style: ast::AttrStyle,
@@ -913,12 +896,30 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::Ne => "!=".into(),
             token::Ge => ">=".into(),
             token::Gt => ">".into(),
-            token::Not => "!".into(),
+            token::Bang => "!".into(),
             token::Tilde => "~".into(),
             token::OrOr => "||".into(),
             token::AndAnd => "&&".into(),
-            token::BinOp(op) => binop_to_string(op).into(),
-            token::BinOpEq(op) => format!("{}=", binop_to_string(op)).into(),
+            token::Plus => "+".into(),
+            token::Minus => "-".into(),
+            token::Star => "*".into(),
+            token::Slash => "/".into(),
+            token::Percent => "%".into(),
+            token::Caret => "^".into(),
+            token::And => "&".into(),
+            token::Or => "|".into(),
+            token::Shl => "<<".into(),
+            token::Shr => ">>".into(),
+            token::PlusEq => "+=".into(),
+            token::MinusEq => "-=".into(),
+            token::StarEq => "*=".into(),
+            token::SlashEq => "/=".into(),
+            token::PercentEq => "%=".into(),
+            token::CaretEq => "^=".into(),
+            token::AndEq => "&=".into(),
+            token::OrEq => "|=".into(),
+            token::ShlEq => "<<=".into(),
+            token::ShrEq => ">>=".into(),
 
             /* Structural symbols */
             token::At => "@".into(),
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index c10b5ad34e1..ced0cbd2fef 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -735,7 +735,8 @@ impl<'a> State<'a> {
     }
 
     pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
-        let ast::WherePredicate { kind, id: _, span: _ } = predicate;
+        let ast::WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
+        self.print_outer_attributes(attrs);
         match kind {
             ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => {
                 self.print_where_bound_predicate(where_bound_predicate);
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 5aed9f76f14..46b79e09780 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -300,13 +300,16 @@ pub(crate) fn expand_deriving_coerce_pointee(
                 to_ty: &s_ty,
                 rewritten: false,
             };
-            let mut predicate = ast::WherePredicate {
-                kind: ast::WherePredicateKind::BoundPredicate(bound.clone()),
-                span: predicate.span,
-                id: ast::DUMMY_NODE_ID,
-            };
-            substitution.visit_where_predicate(&mut predicate);
+            let mut kind = ast::WherePredicateKind::BoundPredicate(bound.clone());
+            substitution.visit_where_predicate_kind(&mut kind);
             if substitution.rewritten {
+                let predicate = ast::WherePredicate {
+                    attrs: predicate.attrs.clone(),
+                    kind,
+                    span: predicate.span,
+                    id: ast::DUMMY_NODE_ID,
+                    is_placeholder: false,
+                };
                 impl_generics.where_clause.predicates.push(predicate);
             }
         }
@@ -388,8 +391,8 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> {
         }
     }
 
-    fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) {
-        match &mut where_predicate.kind {
+    fn visit_where_predicate_kind(&mut self, kind: &mut ast::WherePredicateKind) {
+        match kind {
             rustc_ast::WherePredicateKind::BoundPredicate(bound) => {
                 bound
                     .bound_generic_params
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 6b59ac25827..5402b5a1ae9 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -687,9 +687,11 @@ impl<'a> TraitDef<'a> {
         // and similarly for where clauses
         where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
             ast::WherePredicate {
+                attrs: clause.attrs.clone(),
                 kind: clause.kind.clone(),
                 id: ast::DUMMY_NODE_ID,
                 span: clause.span.with_ctxt(ctxt),
+                is_placeholder: false,
             }
         }));
 
@@ -744,8 +746,13 @@ impl<'a> TraitDef<'a> {
                         };
 
                         let kind = ast::WherePredicateKind::BoundPredicate(predicate);
-                        let predicate =
-                            ast::WherePredicate { kind, id: ast::DUMMY_NODE_ID, span: self.span };
+                        let predicate = ast::WherePredicate {
+                            attrs: ThinVec::new(),
+                            kind,
+                            id: ast::DUMMY_NODE_ID,
+                            span: self.span,
+                            is_placeholder: false,
+                        };
                         where_clause.predicates.push(predicate);
                     }
                 }
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 90447da6680..6dbd8a7ac01 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -190,7 +190,8 @@ fn make_format_args(
                                 && let [stmt] = block.stmts.as_slice()
                                 && let StmtKind::Expr(expr) = &stmt.kind
                                 && let ExprKind::Path(None, path) = &expr.kind
-                                && path.is_potential_trivial_const_arg()
+                                && path.segments.len() == 1
+                                && path.segments[0].args.is_none()
                             {
                                 err.multipart_suggestion(
                                     "quote your inlined format argument to use as string literal",
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
index bedc6ca11b3..d8db7d63f2d 100644
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
@@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644
  
  [dependencies]
  core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] }
+-compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] }
++compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] }
  
  [dev-dependencies]
  rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 20a3482aaa2..628e34badf9 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -64,11 +64,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
     }
 
-    fn is_undef(&self, _val: RValue<'gcc>) -> bool {
-        // FIXME: actually check for undef
-        false
-    }
-
     fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
         let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined");
         if typ.is_struct().is_some() {
@@ -146,13 +141,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) {
-        let str_global = *self
-            .const_str_cache
-            .borrow_mut()
-            .raw_entry_mut()
-            .from_key(s)
-            .or_insert_with(|| (s.to_owned(), self.global_string(s)))
-            .1;
+        let mut const_str_cache = self.const_str_cache.borrow_mut();
+        let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
+            let g = self.global_string(s);
+            const_str_cache.insert(s.to_owned(), g);
+            g
+        });
         let len = s.len();
         let cs = self.const_ptrcast(
             str_global.get_address(None),
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 9d91aab72ab..f090597f953 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -16,7 +16,7 @@
 #![allow(internal_features)]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)]
+#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)]
 #![allow(broken_intra_doc_links)]
 #![recursion_limit = "256"]
 #![warn(rust_2018_idioms)]
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 0621b893e75..f264e3419e4 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -127,10 +127,6 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         unsafe { llvm::LLVMGetUndef(t) }
     }
 
-    fn is_undef(&self, v: &'ll Value) -> bool {
-        unsafe { llvm::LLVMIsUndef(v) == True }
-    }
-
     fn const_poison(&self, t: &'ll Type) -> &'ll Value {
         unsafe { llvm::LLVMGetPoison(t) }
     }
@@ -209,28 +205,24 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 
     fn const_str(&self, s: &str) -> (&'ll Value, &'ll Value) {
-        let str_global = *self
-            .const_str_cache
-            .borrow_mut()
-            .raw_entry_mut()
-            .from_key(s)
-            .or_insert_with(|| {
-                let sc = self.const_bytes(s.as_bytes());
-                let sym = self.generate_local_symbol_name("str");
-                let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
-                    bug!("symbol `{}` is already defined", sym);
-                });
-                llvm::set_initializer(g, sc);
-                unsafe {
-                    llvm::LLVMSetGlobalConstant(g, True);
-                    llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
-                }
-                llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
-                // Cast to default address space if globals are in a different addrspace
-                let g = self.const_pointercast(g, self.type_ptr());
-                (s.to_owned(), g)
-            })
-            .1;
+        let mut const_str_cache = self.const_str_cache.borrow_mut();
+        let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
+            let sc = self.const_bytes(s.as_bytes());
+            let sym = self.generate_local_symbol_name("str");
+            let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
+                bug!("symbol `{}` is already defined", sym);
+            });
+            llvm::set_initializer(g, sc);
+            unsafe {
+                llvm::LLVMSetGlobalConstant(g, True);
+                llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
+            }
+            llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
+            // Cast to default address space if globals are in a different addrspace
+            let g = self.const_pointercast(g, self.type_ptr());
+            const_str_cache.insert(s.to_owned(), g);
+            g
+        });
         let len = s.len();
         (str_global, self.const_usize(len as u64))
     }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index c88372db491..8f72307eeba 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -12,7 +12,6 @@
 #![feature(exact_size_is_empty)]
 #![feature(extern_types)]
 #![feature(file_buffered)]
-#![feature(hash_raw_entry)]
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 2dc14e4613d..e3d0b928c97 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1046,7 +1046,6 @@ unsafe extern "C" {
     pub(crate) fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
 
     // Operations on all values
-    pub(crate) fn LLVMIsUndef(Val: &Value) -> Bool;
     pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type;
     pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
     pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 22e262546c3..f15d6fba506 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -119,7 +119,8 @@ codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of
 
 codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
-codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: found mask element type is `{$ty}`, expected a signed integer type
+    .note = the mask may be widened, which only has the correct behavior for signed integers
 
 codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 5054ae561c0..a170b2e3b6a 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,3 +1,5 @@
+mod raw_dylib;
+
 use std::collections::BTreeSet;
 use std::ffi::OsString;
 use std::fs::{File, OpenOptions, read};
@@ -12,7 +14,7 @@ use itertools::Itertools;
 use regex::Regex;
 use rustc_arena::TypedArena;
 use rustc_ast::CRATE_NODE_ID;
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
@@ -30,7 +32,6 @@ use rustc_session::config::{
     self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
     OutputType, PrintKind, SplitDwarfKind, Strip,
 };
-use rustc_session::cstore::DllImport;
 use rustc_session::lint::builtin::LINKER_MESSAGES;
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
 use rustc_session::search_paths::PathKind;
@@ -41,22 +42,21 @@ use rustc_session::{Session, filesearch};
 use rustc_span::Symbol;
 use rustc_target::spec::crt_objects::CrtObjects;
 use rustc_target::spec::{
-    Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures,
-    LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
-    SplitDebuginfo,
+    BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault,
+    LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel,
+    SanitizerSet, SplitDebuginfo,
 };
 use tempfile::Builder as TempFileBuilder;
 use tracing::{debug, info, warn};
 
-use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
+use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::metadata::{MetadataPosition, create_wrapper_file};
 use super::rpath::{self, RPathConfig};
 use super::{apple, versioned_llvm_target};
 use crate::{
-    CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors,
-    looks_like_rust_object_file,
+    CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file,
 };
 
 pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
@@ -376,16 +376,22 @@ fn link_rlib<'a>(
         }
     }
 
-    for output_path in create_dll_import_libs(
-        sess,
-        archive_builder_builder,
-        codegen_results.crate_info.used_libraries.iter(),
-        tmpdir.as_ref(),
-        true,
-    ) {
-        ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
-            sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
-        });
+    // On Windows, we add the raw-dylib import libraries to the rlibs already.
+    // But on ELF, this is not possible, as a shared object cannot be a member of a static library.
+    // Instead, we add all raw-dylibs to the final link on ELF.
+    if sess.target.is_like_windows {
+        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
+            sess,
+            archive_builder_builder,
+            codegen_results.crate_info.used_libraries.iter(),
+            tmpdir.as_ref(),
+            true,
+        ) {
+            ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
+                sess.dcx()
+                    .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
+            });
+        }
     }
 
     if let Some(trailing_metadata) = trailing_metadata {
@@ -426,108 +432,6 @@ fn link_rlib<'a>(
     ab
 }
 
-/// Extract all symbols defined in raw-dylib libraries, collated by library name.
-///
-/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
-/// then the CodegenResults value contains one NativeLib instance for each block. However, the
-/// linker appears to expect only a single import library for each library used, so we need to
-/// collate the symbols together by library name before generating the import libraries.
-fn collate_raw_dylibs<'a>(
-    sess: &Session,
-    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
-) -> Vec<(String, Vec<DllImport>)> {
-    // Use index maps to preserve original order of imports and libraries.
-    let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
-
-    for lib in used_libraries {
-        if lib.kind == NativeLibKind::RawDylib {
-            let ext = if lib.verbatim { "" } else { ".dll" };
-            let name = format!("{}{}", lib.name, ext);
-            let imports = dylib_table.entry(name.clone()).or_default();
-            for import in &lib.dll_imports {
-                if let Some(old_import) = imports.insert(import.name, import) {
-                    // FIXME: when we add support for ordinals, figure out if we need to do anything
-                    // if we have two DllImport values with the same name but different ordinals.
-                    if import.calling_convention != old_import.calling_convention {
-                        sess.dcx().emit_err(errors::MultipleExternalFuncDecl {
-                            span: import.span,
-                            function: import.name,
-                            library_name: &name,
-                        });
-                    }
-                }
-            }
-        }
-    }
-    sess.dcx().abort_if_errors();
-    dylib_table
-        .into_iter()
-        .map(|(name, imports)| {
-            (name, imports.into_iter().map(|(_, import)| import.clone()).collect())
-        })
-        .collect()
-}
-
-fn create_dll_import_libs<'a>(
-    sess: &Session,
-    archive_builder_builder: &dyn ArchiveBuilderBuilder,
-    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
-    tmpdir: &Path,
-    is_direct_dependency: bool,
-) -> Vec<PathBuf> {
-    collate_raw_dylibs(sess, used_libraries)
-        .into_iter()
-        .map(|(raw_dylib_name, raw_dylib_imports)| {
-            let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
-            let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
-
-            let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
-
-            let items: Vec<ImportLibraryItem> = raw_dylib_imports
-                .iter()
-                .map(|import: &DllImport| {
-                    if sess.target.arch == "x86" {
-                        ImportLibraryItem {
-                            name: common::i686_decorated_name(
-                                import,
-                                mingw_gnu_toolchain,
-                                false,
-                                false,
-                            ),
-                            ordinal: import.ordinal(),
-                            symbol_name: import.is_missing_decorations().then(|| {
-                                common::i686_decorated_name(
-                                    import,
-                                    mingw_gnu_toolchain,
-                                    false,
-                                    true,
-                                )
-                            }),
-                            is_data: !import.is_fn,
-                        }
-                    } else {
-                        ImportLibraryItem {
-                            name: import.name.to_string(),
-                            ordinal: import.ordinal(),
-                            symbol_name: None,
-                            is_data: !import.is_fn,
-                        }
-                    }
-                })
-                .collect();
-
-            archive_builder_builder.create_dll_import_lib(
-                sess,
-                &raw_dylib_name,
-                items,
-                &output_path,
-            );
-
-            output_path
-        })
-        .collect()
-}
-
 /// Create a static archive.
 ///
 /// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@@ -2422,15 +2326,39 @@ fn linker_with_args(
         link_output_kind,
     );
 
+    // Raw-dylibs from all crates.
+    let raw_dylib_dir = tmpdir.join("raw-dylibs");
+    if sess.target.binary_format == BinaryFormat::Elf {
+        // On ELF we can't pass the raw-dylibs stubs to the linker as a path,
+        // instead we need to pass them via -l. To find the stub, we need to add
+        // the directory of the stub to the linker search path.
+        // We make an extra directory for this to avoid polluting the search path.
+        if let Err(error) = fs::create_dir(&raw_dylib_dir) {
+            sess.dcx().emit_fatal(errors::CreateTempDir { error })
+        }
+        cmd.include_path(&raw_dylib_dir);
+    }
+
     // Link with the import library generated for any raw-dylib functions.
-    for output_path in create_dll_import_libs(
-        sess,
-        archive_builder_builder,
-        codegen_results.crate_info.used_libraries.iter(),
-        tmpdir,
-        true,
-    ) {
-        cmd.add_object(&output_path);
+    if sess.target.is_like_windows {
+        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
+            sess,
+            archive_builder_builder,
+            codegen_results.crate_info.used_libraries.iter(),
+            tmpdir,
+            true,
+        ) {
+            cmd.add_object(&output_path);
+        }
+    } else {
+        for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
+            sess,
+            codegen_results.crate_info.used_libraries.iter(),
+            &raw_dylib_dir,
+        ) {
+            // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
+            cmd.link_dylib_by_name(&link_path, true, false);
+        }
     }
     // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
     // they are used within inlined functions or instantiated generic functions. We do this *after*
@@ -2449,19 +2377,35 @@ fn linker_with_args(
         .native_libraries
         .iter()
         .filter_map(|(&cnum, libraries)| {
-            (dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
+            if sess.target.is_like_windows {
+                (dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
+            } else {
+                Some(libraries)
+            }
         })
         .flatten()
         .collect::<Vec<_>>();
     native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
-    for output_path in create_dll_import_libs(
-        sess,
-        archive_builder_builder,
-        native_libraries_from_nonstatics,
-        tmpdir,
-        false,
-    ) {
-        cmd.add_object(&output_path);
+
+    if sess.target.is_like_windows {
+        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
+            sess,
+            archive_builder_builder,
+            native_libraries_from_nonstatics,
+            tmpdir,
+            false,
+        ) {
+            cmd.add_object(&output_path);
+        }
+    } else {
+        for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
+            sess,
+            native_libraries_from_nonstatics,
+            &raw_dylib_dir,
+        ) {
+            // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
+            cmd.link_dylib_by_name(&link_path, true, false);
+        }
     }
 
     // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
new file mode 100644
index 00000000000..2c24378afe1
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
@@ -0,0 +1,373 @@
+use std::fs;
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
+use rustc_abi::Endian;
+use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_hashes::Hash128;
+use rustc_session::Session;
+use rustc_session::cstore::DllImport;
+use rustc_session::utils::NativeLibKind;
+use rustc_span::Symbol;
+
+use crate::back::archive::ImportLibraryItem;
+use crate::back::link::ArchiveBuilderBuilder;
+use crate::errors::ErrorCreatingImportLibrary;
+use crate::{NativeLib, common, errors};
+
+/// Extract all symbols defined in raw-dylib libraries, collated by library name.
+///
+/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
+/// then the CodegenResults value contains one NativeLib instance for each block. However, the
+/// linker appears to expect only a single import library for each library used, so we need to
+/// collate the symbols together by library name before generating the import libraries.
+fn collate_raw_dylibs_windows<'a>(
+    sess: &Session,
+    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+) -> Vec<(String, Vec<DllImport>)> {
+    // Use index maps to preserve original order of imports and libraries.
+    let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
+
+    for lib in used_libraries {
+        if lib.kind == NativeLibKind::RawDylib {
+            let ext = if lib.verbatim { "" } else { ".dll" };
+            let name = format!("{}{}", lib.name, ext);
+            let imports = dylib_table.entry(name.clone()).or_default();
+            for import in &lib.dll_imports {
+                if let Some(old_import) = imports.insert(import.name, import) {
+                    // FIXME: when we add support for ordinals, figure out if we need to do anything
+                    // if we have two DllImport values with the same name but different ordinals.
+                    if import.calling_convention != old_import.calling_convention {
+                        sess.dcx().emit_err(errors::MultipleExternalFuncDecl {
+                            span: import.span,
+                            function: import.name,
+                            library_name: &name,
+                        });
+                    }
+                }
+            }
+        }
+    }
+    sess.dcx().abort_if_errors();
+    dylib_table
+        .into_iter()
+        .map(|(name, imports)| {
+            (name, imports.into_iter().map(|(_, import)| import.clone()).collect())
+        })
+        .collect()
+}
+
+pub(super) fn create_raw_dylib_dll_import_libs<'a>(
+    sess: &Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
+    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+    tmpdir: &Path,
+    is_direct_dependency: bool,
+) -> Vec<PathBuf> {
+    collate_raw_dylibs_windows(sess, used_libraries)
+        .into_iter()
+        .map(|(raw_dylib_name, raw_dylib_imports)| {
+            let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
+            let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
+
+            let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
+
+            let items: Vec<ImportLibraryItem> = raw_dylib_imports
+                .iter()
+                .map(|import: &DllImport| {
+                    if sess.target.arch == "x86" {
+                        ImportLibraryItem {
+                            name: common::i686_decorated_name(
+                                import,
+                                mingw_gnu_toolchain,
+                                false,
+                                false,
+                            ),
+                            ordinal: import.ordinal(),
+                            symbol_name: import.is_missing_decorations().then(|| {
+                                common::i686_decorated_name(
+                                    import,
+                                    mingw_gnu_toolchain,
+                                    false,
+                                    true,
+                                )
+                            }),
+                            is_data: !import.is_fn,
+                        }
+                    } else {
+                        ImportLibraryItem {
+                            name: import.name.to_string(),
+                            ordinal: import.ordinal(),
+                            symbol_name: None,
+                            is_data: !import.is_fn,
+                        }
+                    }
+                })
+                .collect();
+
+            archive_builder_builder.create_dll_import_lib(
+                sess,
+                &raw_dylib_name,
+                items,
+                &output_path,
+            );
+
+            output_path
+        })
+        .collect()
+}
+
+/// Extract all symbols defined in raw-dylib libraries, collated by library name.
+///
+/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
+/// then the CodegenResults value contains one NativeLib instance for each block. However, the
+/// linker appears to expect only a single import library for each library used, so we need to
+/// collate the symbols together by library name before generating the import libraries.
+fn collate_raw_dylibs_elf<'a>(
+    sess: &Session,
+    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+) -> Vec<(String, Vec<DllImport>)> {
+    // Use index maps to preserve original order of imports and libraries.
+    let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
+
+    for lib in used_libraries {
+        if lib.kind == NativeLibKind::RawDylib {
+            let filename = if lib.verbatim {
+                lib.name.as_str().to_owned()
+            } else {
+                let ext = sess.target.dll_suffix.as_ref();
+                let prefix = sess.target.dll_prefix.as_ref();
+                format!("{prefix}{}{ext}", lib.name)
+            };
+
+            let imports = dylib_table.entry(filename.clone()).or_default();
+            for import in &lib.dll_imports {
+                imports.insert(import.name, import);
+            }
+        }
+    }
+    sess.dcx().abort_if_errors();
+    dylib_table
+        .into_iter()
+        .map(|(name, imports)| {
+            (name, imports.into_iter().map(|(_, import)| import.clone()).collect())
+        })
+        .collect()
+}
+
+pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
+    sess: &Session,
+    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+    raw_dylib_so_dir: &Path,
+) -> Vec<String> {
+    collate_raw_dylibs_elf(sess, used_libraries)
+        .into_iter()
+        .map(|(load_filename, raw_dylib_imports)| {
+            use std::hash::Hash;
+
+            // `load_filename` is the *target/loader* filename that will end up in NEEDED.
+            // Usually this will be something like `libc.so` or `libc.so.6` but with
+            // verbatim it might also be an absolute path.
+            // To be able to support this properly, we always put this load filename
+            // into the SONAME of the library and link it via a temporary file with a random name.
+            // This also avoids naming conflicts with non-raw-dylib linkage of the same library.
+
+            let shared_object = create_elf_raw_dylib_stub(sess, &load_filename, &raw_dylib_imports);
+
+            let mut file_name_hasher = StableHasher::new();
+            load_filename.hash(&mut file_name_hasher);
+            for raw_dylib in raw_dylib_imports {
+                raw_dylib.name.as_str().hash(&mut file_name_hasher);
+            }
+
+            let library_filename: Hash128 = file_name_hasher.finish();
+            let temporary_lib_name = format!(
+                "{}{}{}",
+                sess.target.dll_prefix,
+                library_filename.as_u128().to_base_fixed_len(CASE_INSENSITIVE),
+                sess.target.dll_suffix
+            );
+            let link_path = raw_dylib_so_dir.join(&temporary_lib_name);
+
+            let file = match fs::File::create_new(&link_path) {
+                Ok(file) => file,
+                Err(error) => sess.dcx().emit_fatal(ErrorCreatingImportLibrary {
+                    lib_name: &load_filename,
+                    error: error.to_string(),
+                }),
+            };
+            if let Err(error) = BufWriter::new(file).write_all(&shared_object) {
+                sess.dcx().emit_fatal(ErrorCreatingImportLibrary {
+                    lib_name: &load_filename,
+                    error: error.to_string(),
+                });
+            };
+
+            temporary_lib_name
+        })
+        .collect()
+}
+
+/// Create an ELF .so stub file for raw-dylib.
+/// It exports all the provided symbols, but is otherwise empty.
+fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]) -> Vec<u8> {
+    use object::write::elf as write;
+    use object::{Architecture, elf};
+
+    let mut stub_buf = Vec::new();
+
+    // Build the stub ELF using the object crate.
+    // The high-level portable API does not allow for the fine-grained control we need,
+    // so this uses the low-level object::write::elf API.
+    // The low-level API consists of two stages: reservation and writing.
+    // We first reserve space for all the things in the binary and then write them.
+    // It is important that the order of reservation matches the order of writing.
+    // The object crate contains many debug asserts that fire if you get this wrong.
+
+    let endianness = match sess.target.options.endian {
+        Endian::Little => object::Endianness::Little,
+        Endian::Big => object::Endianness::Big,
+    };
+    let mut stub = write::Writer::new(endianness, true, &mut stub_buf);
+
+    // These initial reservations don't reserve any bytes in the binary yet,
+    // they just allocate in the internal data structures.
+
+    // First, we crate the dynamic symbol table. It starts with a null symbol
+    // and then all the symbols and their dynamic strings.
+    stub.reserve_null_dynamic_symbol_index();
+
+    let dynstrs = symbols
+        .iter()
+        .map(|sym| {
+            stub.reserve_dynamic_symbol_index();
+            (sym, stub.add_dynamic_string(sym.name.as_str().as_bytes()))
+        })
+        .collect::<Vec<_>>();
+
+    let soname = stub.add_dynamic_string(soname.as_bytes());
+
+    // Reserve the sections.
+    // We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to.
+    stub.reserve_shstrtab_section_index();
+    let text_section_name = stub.add_section_name(".text".as_bytes());
+    let text_section = stub.reserve_section_index();
+    stub.reserve_dynstr_section_index();
+    stub.reserve_dynsym_section_index();
+    stub.reserve_dynamic_section_index();
+
+    // These reservations now determine the actual layout order of the object file.
+    stub.reserve_file_header();
+    stub.reserve_shstrtab();
+    stub.reserve_section_headers();
+    stub.reserve_dynstr();
+    stub.reserve_dynsym();
+    stub.reserve_dynamic(2); // DT_SONAME, DT_NULL
+
+    // First write the ELF header with the arch information.
+    let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features)
+    else {
+        sess.dcx().fatal(format!(
+            "raw-dylib is not supported for the architecture `{}`",
+            sess.target.arch
+        ));
+    };
+    let e_machine = match (arch, sub_arch) {
+        (Architecture::Aarch64, None) => elf::EM_AARCH64,
+        (Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64,
+        (Architecture::Arm, None) => elf::EM_ARM,
+        (Architecture::Avr, None) => elf::EM_AVR,
+        (Architecture::Bpf, None) => elf::EM_BPF,
+        (Architecture::Csky, None) => elf::EM_CSKY,
+        (Architecture::E2K32, None) => elf::EM_MCST_ELBRUS,
+        (Architecture::E2K64, None) => elf::EM_MCST_ELBRUS,
+        (Architecture::I386, None) => elf::EM_386,
+        (Architecture::X86_64, None) => elf::EM_X86_64,
+        (Architecture::X86_64_X32, None) => elf::EM_X86_64,
+        (Architecture::Hexagon, None) => elf::EM_HEXAGON,
+        (Architecture::LoongArch64, None) => elf::EM_LOONGARCH,
+        (Architecture::M68k, None) => elf::EM_68K,
+        (Architecture::Mips, None) => elf::EM_MIPS,
+        (Architecture::Mips64, None) => elf::EM_MIPS,
+        (Architecture::Mips64_N32, None) => elf::EM_MIPS,
+        (Architecture::Msp430, None) => elf::EM_MSP430,
+        (Architecture::PowerPc, None) => elf::EM_PPC,
+        (Architecture::PowerPc64, None) => elf::EM_PPC64,
+        (Architecture::Riscv32, None) => elf::EM_RISCV,
+        (Architecture::Riscv64, None) => elf::EM_RISCV,
+        (Architecture::S390x, None) => elf::EM_S390,
+        (Architecture::Sbf, None) => elf::EM_SBF,
+        (Architecture::Sharc, None) => elf::EM_SHARC,
+        (Architecture::Sparc, None) => elf::EM_SPARC,
+        (Architecture::Sparc32Plus, None) => elf::EM_SPARC32PLUS,
+        (Architecture::Sparc64, None) => elf::EM_SPARCV9,
+        (Architecture::Xtensa, None) => elf::EM_XTENSA,
+        _ => {
+            sess.dcx().fatal(format!(
+                "raw-dylib is not supported for the architecture `{}`",
+                sess.target.arch
+            ));
+        }
+    };
+
+    stub.write_file_header(&write::FileHeader {
+        os_abi: crate::back::metadata::elf_os_abi(sess),
+        abi_version: 0,
+        e_type: object::elf::ET_DYN,
+        e_machine,
+        e_entry: 0,
+        e_flags: crate::back::metadata::elf_e_flags(arch, sess),
+    })
+    .unwrap();
+
+    // .shstrtab
+    stub.write_shstrtab();
+
+    // Section headers
+    stub.write_null_section_header();
+    stub.write_shstrtab_section_header();
+    // Create a dummy .text section for our dummy symbols.
+    stub.write_section_header(&write::SectionHeader {
+        name: Some(text_section_name),
+        sh_type: elf::SHT_PROGBITS,
+        sh_flags: 0,
+        sh_addr: 0,
+        sh_offset: 0,
+        sh_size: 0,
+        sh_link: 0,
+        sh_info: 0,
+        sh_addralign: 1,
+        sh_entsize: 0,
+    });
+    stub.write_dynstr_section_header(0);
+    stub.write_dynsym_section_header(0, 1);
+    stub.write_dynamic_section_header(0);
+
+    // .dynstr
+    stub.write_dynstr();
+
+    // .dynsym
+    stub.write_null_dynamic_symbol();
+    for (_, name) in dynstrs {
+        stub.write_dynamic_symbol(&write::Sym {
+            name: Some(name),
+            st_info: (elf::STB_GLOBAL << 4) | elf::STT_NOTYPE,
+            st_other: elf::STV_DEFAULT,
+            section: Some(text_section),
+            st_shndx: 0, // ignored by object in favor of the `section` field
+            st_value: 0,
+            st_size: 0,
+        });
+    }
+
+    // .dynamic
+    // the DT_SONAME will be used by the linker to populate DT_NEEDED
+    // which the loader uses to find the library.
+    // DT_NULL terminates the .dynamic table.
+    stub.write_dynamic_string(elf::DT_SONAME, soname);
+    stub.write_dynamic(elf::DT_NULL, 0);
+
+    stub_buf
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 3aacbcde1a7..68b453ff424 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -9,8 +9,7 @@ use itertools::Itertools;
 use object::write::{self, StandardSegment, Symbol, SymbolSection};
 use object::{
     Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol,
-    SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe,
-    xcoff,
+    SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff,
 };
 use rustc_abi::Endian;
 use rustc_data_structures::memmap::Mmap;
@@ -206,51 +205,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Endian::Little => Endianness::Little,
         Endian::Big => Endianness::Big,
     };
-    let (architecture, sub_architecture) = match &sess.target.arch[..] {
-        "arm" => (Architecture::Arm, None),
-        "aarch64" => (
-            if sess.target.pointer_width == 32 {
-                Architecture::Aarch64_Ilp32
-            } else {
-                Architecture::Aarch64
-            },
-            None,
-        ),
-        "x86" => (Architecture::I386, None),
-        "s390x" => (Architecture::S390x, None),
-        "mips" | "mips32r6" => (Architecture::Mips, None),
-        "mips64" | "mips64r6" => (Architecture::Mips64, None),
-        "x86_64" => (
-            if sess.target.pointer_width == 32 {
-                Architecture::X86_64_X32
-            } else {
-                Architecture::X86_64
-            },
-            None,
-        ),
-        "powerpc" => (Architecture::PowerPc, None),
-        "powerpc64" => (Architecture::PowerPc64, None),
-        "riscv32" => (Architecture::Riscv32, None),
-        "riscv64" => (Architecture::Riscv64, None),
-        "sparc" => {
-            if sess.unstable_target_features.contains(&sym::v8plus) {
-                // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode
-                (Architecture::Sparc32Plus, None)
-            } else {
-                // Target uses V7 or V8, aka EM_SPARC
-                (Architecture::Sparc, None)
-            }
-        }
-        "sparc64" => (Architecture::Sparc64, None),
-        "avr" => (Architecture::Avr, None),
-        "msp430" => (Architecture::Msp430, None),
-        "hexagon" => (Architecture::Hexagon, None),
-        "bpf" => (Architecture::Bpf, None),
-        "loongarch64" => (Architecture::LoongArch64, None),
-        "csky" => (Architecture::Csky, None),
-        "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)),
-        // Unsupported architecture.
-        _ => return None,
+    let Some((architecture, sub_architecture)) =
+        sess.target.object_architecture(&sess.unstable_target_features)
+    else {
+        return None;
     };
     let binary_format = sess.target.binary_format.to_object();
 
@@ -292,7 +250,26 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
 
         file.set_mangling(original_mangling);
     }
-    let e_flags = match architecture {
+    let e_flags = elf_e_flags(architecture, sess);
+    // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
+    let os_abi = elf_os_abi(sess);
+    let abi_version = 0;
+    add_gnu_property_note(&mut file, architecture, binary_format, endianness);
+    file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
+    Some(file)
+}
+
+pub(super) fn elf_os_abi(sess: &Session) -> u8 {
+    match sess.target.options.os.as_ref() {
+        "hermit" => elf::ELFOSABI_STANDALONE,
+        "freebsd" => elf::ELFOSABI_FREEBSD,
+        "solaris" => elf::ELFOSABI_SOLARIS,
+        _ => elf::ELFOSABI_NONE,
+    }
+}
+
+pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
+    match architecture {
         Architecture::Mips => {
             let arch = match sess.target.options.cpu.as_ref() {
                 "mips1" => elf::EF_MIPS_ARCH_1,
@@ -387,18 +364,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
             e_flags
         }
         _ => 0,
-    };
-    // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
-    let os_abi = match sess.target.options.os.as_ref() {
-        "hermit" => elf::ELFOSABI_STANDALONE,
-        "freebsd" => elf::ELFOSABI_FREEBSD,
-        "solaris" => elf::ELFOSABI_SOLARIS,
-        _ => elf::ELFOSABI_NONE,
-    };
-    let abi_version = 0;
-    add_gnu_property_note(&mut file, architecture, binary_format, endianness);
-    file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
-    Some(file)
+    }
 }
 
 /// Mach-O files contain information about:
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 7e28961599f..ccf6d12977f 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -957,6 +957,7 @@ pub enum InvalidMonomorphization<'tcx> {
     },
 
     #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = E0511)]
+    #[note]
     MaskType {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 4b33bdeadba..acae09b2c25 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -203,30 +203,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let alloc_align = alloc.inner().align;
         assert!(alloc_align >= layout.align.abi);
 
-        // Returns `None` when the value is partially undefined or any byte of it has provenance.
-        // Otherwise returns the value or (if the entire value is undef) returns an undef.
         let read_scalar = |start, size, s: abi::Scalar, ty| {
-            let range = alloc_range(start, size);
             match alloc.0.read_scalar(
                 bx,
-                range,
+                alloc_range(start, size),
                 /*read_provenance*/ matches!(s.primitive(), abi::Primitive::Pointer(_)),
             ) {
-                Ok(val) => Some(bx.scalar_to_backend(val, s, ty)),
-                Err(_) => {
-                    // We may have failed due to partial provenance or unexpected provenance,
-                    // continue down the normal code path if so.
-                    if alloc.0.provenance().range_empty(range, &bx.tcx())
-                        // Since `read_scalar` failed, but there were no relocations involved, the
-                        // bytes must be partially or fully uninitialized. Thus we can now unwrap the
-                        // information about the range of uninit bytes and check if it's the full range.
-                        && alloc.0.init_mask().is_range_initialized(range).unwrap_err() == range
-                    {
-                        Some(bx.const_undef(ty))
-                    } else {
-                        None
-                    }
-                }
+                Ok(val) => bx.scalar_to_backend(val, s, ty),
+                Err(_) => bx.const_poison(ty),
             }
         };
 
@@ -237,14 +221,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         // check that walks over the type of `mplace` to make sure it is truly correct to treat this
         // like a `Scalar` (or `ScalarPair`).
         match layout.backend_repr {
-            BackendRepr::Scalar(s) => {
+            BackendRepr::Scalar(s @ abi::Scalar::Initialized { .. }) => {
                 let size = s.size(bx);
                 assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
-                if let Some(val) = read_scalar(offset, size, s, bx.immediate_backend_type(layout)) {
-                    return OperandRef { val: OperandValue::Immediate(val), layout };
-                }
+                let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout));
+                OperandRef { val: OperandValue::Immediate(val), layout }
             }
-            BackendRepr::ScalarPair(a, b) => {
+            BackendRepr::ScalarPair(
+                a @ abi::Scalar::Initialized { .. },
+                b @ abi::Scalar::Initialized { .. },
+            ) => {
                 let (a_size, b_size) = (a.size(bx), b.size(bx));
                 let b_offset = (offset + a_size).align_to(b.align(bx).abi);
                 assert!(b_offset.bytes() > 0);
@@ -260,21 +246,20 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     b,
                     bx.scalar_pair_element_backend_type(layout, 1, true),
                 );
-                if let (Some(a_val), Some(b_val)) = (a_val, b_val) {
-                    return OperandRef { val: OperandValue::Pair(a_val, b_val), layout };
-                }
+                OperandRef { val: OperandValue::Pair(a_val, b_val), layout }
+            }
+            _ if layout.is_zst() => OperandRef::zero_sized(layout),
+            _ => {
+                // Neither a scalar nor scalar pair. Load from a place
+                // FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the
+                // same `ConstAllocation`?
+                let init = bx.const_data_from_alloc(alloc);
+                let base_addr = bx.static_addr_of(init, alloc_align, None);
+
+                let llval = bx.const_ptr_byte_offset(base_addr, offset);
+                bx.load_operand(PlaceRef::new_sized(llval, layout))
             }
-            _ if layout.is_zst() => return OperandRef::zero_sized(layout),
-            _ => {}
         }
-        // Neither a scalar nor scalar pair. Load from a place
-        // FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the
-        // same `ConstAllocation`?
-        let init = bx.const_data_from_alloc(alloc);
-        let base_addr = bx.static_addr_of(init, alloc_align, None);
-
-        let llval = bx.const_ptr_byte_offset(base_addr, offset);
-        bx.load_operand(PlaceRef::new_sized(llval, layout))
     }
 
     /// Asserts that this operand refers to a scalar and returns
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 67555d40332..ff555f4273c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_session::config::OptLevel;
 use rustc_span::{DUMMY_SP, Span};
-use tracing::{debug, instrument, trace};
+use tracing::{debug, instrument};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
@@ -93,8 +93,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     return;
                 }
 
-                // If `v` is an integer constant whose value is just a single byte repeated N times,
-                // emit a `memset` filling the entire `dest` with that byte.
                 let try_init_all_same = |bx: &mut Bx, v| {
                     let start = dest.val.llval;
                     let size = bx.const_usize(dest.layout.size.bytes());
@@ -119,33 +117,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     false
                 };
 
-                trace!(?cg_elem.val);
                 match cg_elem.val {
                     OperandValue::Immediate(v) => {
                         if try_init_all_same(bx, v) {
                             return;
                         }
                     }
-                    OperandValue::Pair(a, b) => {
-                        let a_is_undef = bx.cx().is_undef(a);
-                        match (a_is_undef, bx.cx().is_undef(b)) {
-                            // Can happen for uninit unions
-                            (true, true) => {
-                                // FIXME: can we produce better output here?
-                            }
-                            (false, true) | (true, false) => {
-                                let val = if a_is_undef { b } else { a };
-                                if try_init_all_same(bx, val) {
-                                    return;
-                                }
-                            }
-                            (false, false) => {
-                                // FIXME: if both are the same value, use try_init_all_same
-                            }
-                        }
-                    }
-                    OperandValue::ZeroSized => unreachable!("checked above"),
-                    OperandValue::Ref(..) => {}
+                    _ => (),
                 }
 
                 let count = self
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index d8b9bdb55da..95a5e96fe46 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::{Span, Symbol, sym};
-use rustc_target::target_features;
+use rustc_target::target_features::{self, Stability};
 
 use crate::errors;
 
@@ -87,12 +87,17 @@ pub(crate) fn from_target_feature_attr(
                     // But ensure the ABI does not forbid enabling this.
                     // Here we do assume that LLVM doesn't add even more implied features
                     // we don't know about, at least no features that would have ABI effects!
-                    if abi_feature_constraints.incompatible.contains(&name.as_str()) {
-                        tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
-                            span: item.span(),
-                            feature: name.as_str(),
-                            reason: "this feature is incompatible with the target ABI",
-                        });
+                    // We skip this logic in rustdoc, where we want to allow all target features of
+                    // all targets, so we can't check their ABI compatibility and anyway we are not
+                    // generating code so "it's fine".
+                    if !tcx.sess.opts.actually_rustdoc {
+                        if abi_feature_constraints.incompatible.contains(&name.as_str()) {
+                            tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
+                                span: item.span(),
+                                feature: name.as_str(),
+                                reason: "this feature is incompatible with the target ABI",
+                            });
+                        }
                     }
                     target_features.push(TargetFeature { name, implied: name != feature_sym })
                 }
@@ -142,11 +147,38 @@ pub(crate) fn provide(providers: &mut Providers) {
         rust_target_features: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
             if tcx.sess.opts.actually_rustdoc {
-                // rustdoc needs to be able to document functions that use all the features, so
-                // whitelist them all
-                rustc_target::target_features::all_rust_features()
-                    .map(|(a, b)| (a.to_string(), b))
-                    .collect()
+                // HACK: rustdoc would like to pretend that we have all the target features, so we
+                // have to merge all the lists into one. To ensure an unstable target never prevents
+                // a stable one from working, we merge the stability info of all instances of the
+                // same target feature name, with the "most stable" taking precedence. And then we
+                // hope that this doesn't cause issues anywhere else in the compiler...
+                let mut result: UnordMap<String, Stability> = Default::default();
+                for (name, stability) in rustc_target::target_features::all_rust_features() {
+                    use std::collections::hash_map::Entry;
+                    match result.entry(name.to_owned()) {
+                        Entry::Vacant(vacant_entry) => {
+                            vacant_entry.insert(stability);
+                        }
+                        Entry::Occupied(mut occupied_entry) => {
+                            // Merge the two stabilities, "more stable" taking precedence.
+                            match (occupied_entry.get(), stability) {
+                                (Stability::Stable, _)
+                                | (
+                                    Stability::Unstable { .. },
+                                    Stability::Unstable { .. } | Stability::Forbidden { .. },
+                                )
+                                | (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => {
+                                    // The stability in the entry is at least as good as the new one, just keep it.
+                                }
+                                _ => {
+                                    // Overwrite stabilite.
+                                    occupied_entry.insert(stability);
+                                }
+                            }
+                        }
+                    }
+                }
+                result
             } else {
                 tcx.sess
                     .target
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index 5cfb56ebace..dc6b68ceff7 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -9,7 +9,6 @@ pub trait ConstCodegenMethods<'tcx>: BackendTypes {
     /// Generate an uninitialized value (matching uninitialized memory in MIR).
     /// Whether memory is initialized or not is tracked byte-for-byte.
     fn const_undef(&self, t: Self::Type) -> Self::Value;
-    fn is_undef(&self, v: Self::Value) -> bool;
     /// Generate a fake value. Poison always affects the entire value, even if just a single byte is
     /// poison. This can only be used in codepaths that are already UB, i.e., UB-free Rust code
     /// (including code that e.g. copies uninit memory with `MaybeUninit`) can never encounter a
diff --git a/compiler/rustc_data_structures/src/captures.rs b/compiler/rustc_data_structures/src/captures.rs
deleted file mode 100644
index 677ccb31454..00000000000
--- a/compiler/rustc_data_structures/src/captures.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-/// "Signaling" trait used in impl trait to tag lifetimes that you may
-/// need to capture but don't really need for other reasons.
-/// Basically a workaround; see [this comment] for details.
-///
-/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
-pub trait Captures<'a> {}
-
-impl<'a, T: ?Sized> Captures<'a> for T {}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 66d3834d857..a3b62b46919 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -48,7 +48,6 @@ pub use rustc_index::static_assert_size;
 pub mod aligned;
 pub mod base_n;
 pub mod binary_search_util;
-pub mod captures;
 pub mod fingerprint;
 pub mod flat_map_in_place;
 pub mod flock;
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 5a53f8af5f8..e6be9c256f0 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -43,10 +43,10 @@ impl<T> Sharded<T> {
 
     /// The shard is selected by hashing `val` with `FxHasher`.
     #[inline]
-    pub fn get_shard_by_value<K: Hash + ?Sized>(&self, _val: &K) -> &Lock<T> {
+    pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
         match self {
             Self::Single(single) => single,
-            Self::Shards(..) => self.get_shard_by_hash(make_hash(_val)),
+            Self::Shards(..) => self.get_shard_by_hash(make_hash(val)),
         }
     }
 
@@ -56,12 +56,12 @@ impl<T> Sharded<T> {
     }
 
     #[inline]
-    pub fn get_shard_by_index(&self, _i: usize) -> &Lock<T> {
+    pub fn get_shard_by_index(&self, i: usize) -> &Lock<T> {
         match self {
             Self::Single(single) => single,
             Self::Shards(shards) => {
                 // SAFETY: The index gets ANDed with the shard mask, ensuring it is always inbounds.
-                unsafe { &shards.get_unchecked(_i & (SHARDS - 1)).0 }
+                unsafe { &shards.get_unchecked(i & (SHARDS - 1)).0 }
             }
         }
     }
@@ -69,7 +69,7 @@ impl<T> Sharded<T> {
     /// The shard is selected by hashing `val` with `FxHasher`.
     #[inline]
     #[track_caller]
-    pub fn lock_shard_by_value<K: Hash + ?Sized>(&self, _val: &K) -> LockGuard<'_, T> {
+    pub fn lock_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> LockGuard<'_, T> {
         match self {
             Self::Single(single) => {
                 // Synchronization is disabled so use the `lock_assume_no_sync` method optimized
@@ -79,7 +79,7 @@ impl<T> Sharded<T> {
                 // `might_be_dyn_thread_safe` was also false.
                 unsafe { single.lock_assume(Mode::NoSync) }
             }
-            Self::Shards(..) => self.lock_shard_by_hash(make_hash(_val)),
+            Self::Shards(..) => self.lock_shard_by_hash(make_hash(val)),
         }
     }
 
@@ -91,7 +91,7 @@ impl<T> Sharded<T> {
 
     #[inline]
     #[track_caller]
-    pub fn lock_shard_by_index(&self, _i: usize) -> LockGuard<'_, T> {
+    pub fn lock_shard_by_index(&self, i: usize) -> LockGuard<'_, T> {
         match self {
             Self::Single(single) => {
                 // Synchronization is disabled so use the `lock_assume_no_sync` method optimized
@@ -109,7 +109,7 @@ impl<T> Sharded<T> {
                 // always inbounds.
                 // SAFETY (lock_assume_sync): We know `is_dyn_thread_safe` was true when creating
                 // the lock thus `might_be_dyn_thread_safe` was also true.
-                unsafe { shards.get_unchecked(_i & (SHARDS - 1)).0.lock_assume(Mode::Sync) }
+                unsafe { shards.get_unchecked(i & (SHARDS - 1)).0.lock_assume(Mode::Sync) }
             }
         }
     }
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index 066ea03b4ac..a01a420dfbd 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,4 +1,5 @@
 use std::borrow::Borrow;
+use std::cmp::Ordering;
 use std::fmt::Debug;
 use std::mem;
 use std::ops::{Bound, Index, IndexMut, RangeBounds};
@@ -156,6 +157,38 @@ impl<K: Ord, V> SortedMap<K, V> {
         &self.data[start..end]
     }
 
+    /// `sm.range_is_empty(r)` == `sm.range(r).is_empty()`, but is faster.
+    #[inline]
+    pub fn range_is_empty<R>(&self, range: R) -> bool
+    where
+        R: RangeBounds<K>,
+    {
+        // `range` must (via `range_slice_indices`) search for the start and
+        // end separately. But here we can do a single binary search for the
+        // entire range. If a single `x` matching `range` is found then the
+        // range is *not* empty.
+        self.data
+            .binary_search_by(|(x, _)| {
+                // Is `x` below `range`?
+                match range.start_bound() {
+                    Bound::Included(start) if x < start => return Ordering::Less,
+                    Bound::Excluded(start) if x <= start => return Ordering::Less,
+                    _ => {}
+                };
+
+                // Is `x` above `range`?
+                match range.end_bound() {
+                    Bound::Included(end) if x > end => return Ordering::Greater,
+                    Bound::Excluded(end) if x >= end => return Ordering::Greater,
+                    _ => {}
+                };
+
+                // `x` must be within `range`.
+                Ordering::Equal
+            })
+            .is_err()
+    }
+
     #[inline]
     pub fn remove_range<R>(&mut self, range: R)
     where
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 37b54fe38ff..a1cc75c4985 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -18,42 +18,54 @@
 //!
 //! | Type                    | Serial version      | Parallel version                |
 //! | ----------------------- | ------------------- | ------------------------------- |
-//! | `LRef<'a, T>` [^2]      | `&'a mut T`         | `&'a T`                         |
-//! |                         |                     |                                 |
 //! | `Lock<T>`               | `RefCell<T>`        | `RefCell<T>` or                 |
 //! |                         |                     | `parking_lot::Mutex<T>`         |
 //! | `RwLock<T>`             | `RefCell<T>`        | `parking_lot::RwLock<T>`        |
 //! | `MTLock<T>`        [^1] | `T`                 | `Lock<T>`                       |
-//! | `MTLockRef<'a, T>` [^2] | `&'a mut MTLock<T>` | `&'a MTLock<T>`                 |
 //! |                         |                     |                                 |
 //! | `ParallelIterator`      | `Iterator`          | `rayon::iter::ParallelIterator` |
 //!
 //! [^1]: `MTLock` is similar to `Lock`, but the serial version avoids the cost
 //! of a `RefCell`. This is appropriate when interior mutability is not
 //! required.
-//!
-//! [^2]: `MTRef`, `MTLockRef` are type aliases.
 
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 
-pub use crate::marker::*;
+pub use parking_lot::{
+    MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
+    RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
+};
 
-mod lock;
+pub use self::atomic::AtomicU64;
+pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
 #[doc(no_inline)]
-pub use lock::{Lock, LockGuard, Mode};
-
-mod worker_local;
-pub use worker_local::{Registry, WorkerLocal};
+pub use self::lock::{Lock, LockGuard, Mode};
+pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
+pub use self::parallel::{
+    join, par_for_each_in, par_map, parallel_guard, scope, try_par_for_each_in,
+};
+pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
+pub use self::worker_local::{Registry, WorkerLocal};
+pub use crate::marker::*;
 
+mod freeze;
+mod lock;
 mod parallel;
-pub use parallel::{join, par_for_each_in, par_map, parallel_guard, scope, try_par_for_each_in};
-pub use vec::{AppendOnlyIndexVec, AppendOnlyVec};
-
 mod vec;
+mod worker_local;
 
-mod freeze;
-pub use freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
+/// Keep the conditional imports together in a submodule, so that import-sorting
+/// doesn't split them up.
+mod atomic {
+    // Most hosts can just use a regular AtomicU64.
+    #[cfg(target_has_atomic = "64")]
+    pub use std::sync::atomic::AtomicU64;
+
+    // Some 32-bit hosts don't have AtomicU64, so use a fallback.
+    #[cfg(not(target_has_atomic = "64"))]
+    pub use portable_atomic::AtomicU64;
+}
 
 mod mode {
     use std::sync::atomic::{AtomicU8, Ordering};
@@ -97,21 +109,6 @@ mod mode {
 
 // FIXME(parallel_compiler): Get rid of these aliases across the compiler.
 
-pub use std::sync::OnceLock;
-// Use portable AtomicU64 for targets without native 64-bit atomics
-#[cfg(target_has_atomic = "64")]
-pub use std::sync::atomic::AtomicU64;
-
-pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
-pub use parking_lot::{
-    MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
-    RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
-};
-#[cfg(not(target_has_atomic = "64"))]
-pub use portable_atomic::AtomicU64;
-
-pub type LRef<'a, T> = &'a T;
-
 #[derive(Debug, Default)]
 pub struct MTLock<T>(Lock<T>);
 
@@ -142,14 +139,10 @@ impl<T> MTLock<T> {
     }
 }
 
-use parking_lot::RwLock as InnerRwLock;
-
 /// This makes locks panic if they are already held.
 /// It is only useful when you are running in a single thread
 const ERROR_CHECKING: bool = false;
 
-pub type MTLockRef<'a, T> = LRef<'a, MTLock<T>>;
-
 #[derive(Default)]
 #[repr(align(64))]
 pub struct CacheAligned<T>(pub T);
@@ -167,12 +160,12 @@ impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
 }
 
 #[derive(Debug, Default)]
-pub struct RwLock<T>(InnerRwLock<T>);
+pub struct RwLock<T>(parking_lot::RwLock<T>);
 
 impl<T> RwLock<T> {
     #[inline(always)]
     pub fn new(inner: T) -> Self {
-        RwLock(InnerRwLock::new(inner))
+        RwLock(parking_lot::RwLock::new(inner))
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index 402ec9827bb..d75af009850 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -106,6 +106,12 @@ pub struct WorkerLocal<T> {
     registry: Registry,
 }
 
+// This is safe because the `deref` call will return a reference to a `T` unique to each thread
+// or it will panic for threads without an associated local. So there isn't a need for `T` to do
+// it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
+// can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
+unsafe impl<T: Send> Sync for WorkerLocal<T> {}
+
 impl<T> WorkerLocal<T> {
     /// Creates a new worker local where the `initial` closure computes the
     /// value this worker local should take for each thread in the registry.
@@ -132,11 +138,6 @@ impl<T> Deref for WorkerLocal<T> {
     fn deref(&self) -> &T {
         // This is safe because `verify` will only return values less than
         // `self.registry.thread_limit` which is the size of the `self.locals` array.
-
-        // The `deref` call will return a reference to a `T` unique to each thread
-        // or it will panic for threads without an associated local. So there isn't a need for `T` to do
-        // it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
-        // can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
         unsafe { &self.locals.get_unchecked(self.registry.id().verify()).0 }
     }
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md
index d4d26007aa5..b9db8072597 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0373.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0373.md
@@ -3,7 +3,7 @@ A captured variable in a closure may not live long enough.
 Erroneous code example:
 
 ```compile_fail,E0373
-fn foo() -> Box<Fn(u32) -> u32> {
+fn foo() -> Box<dyn Fn(u32) -> u32> {
     let x = 0u32;
     Box::new(|y| x + y)
 }
@@ -42,7 +42,7 @@ This approach moves (or copies, where possible) data into the closure, rather
 than taking references to it. For example:
 
 ```
-fn foo() -> Box<Fn(u32) -> u32> {
+fn foo() -> Box<dyn Fn(u32) -> u32> {
     let x = 0u32;
     Box::new(move |y| x + y)
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0804.md b/compiler/rustc_error_codes/src/error_codes/E0804.md
new file mode 100644
index 00000000000..9a6937c0b52
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0804.md
@@ -0,0 +1,41 @@
+An auto trait cannot be added to the bounds of a `dyn Trait` type via
+a pointer cast.
+
+Erroneous code example:
+
+```rust,edition2021,compile_fail,E0804
+let ptr: *const dyn core::any::Any = &();
+_ = ptr as *const (dyn core::any::Any + Send);
+```
+
+Adding an auto trait can make the vtable invalid, potentially causing
+UB in safe code afterwards. For example:
+
+```rust,edition2021,no_run
+use core::{mem::transmute, ptr::NonNull};
+
+trait Trait {
+    fn f(&self)
+    where
+        Self: Send;
+}
+
+impl Trait for NonNull<()> {
+    fn f(&self) {
+        unreachable!()
+    }
+}
+
+fn main() {
+    let unsend: &dyn Trait = &NonNull::dangling();
+    let bad: &(dyn Trait + Send) = unsafe { transmute(unsend) };
+    // This crashes, since the vtable for `NonNull as dyn Trait` does
+    // not have an entry for `Trait::f`.
+    bad.f();
+}
+```
+
+To fix this error, you can use `transmute` rather than pointer casts,
+but you must ensure that the vtable is valid for the pointer's type
+before calling a method on the trait object or allowing other code to
+do so.
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 098ca42be2b..d53d5678832 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -547,6 +547,7 @@ E0800: 0800,
 E0801: 0801,
 E0802: 0802,
 E0803: 0803,
+E0804: 0804,
         );
     )
 }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 4a250145308..86b12f6be4e 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -53,6 +53,7 @@ pub enum Annotatable {
     Param(ast::Param),
     FieldDef(ast::FieldDef),
     Variant(ast::Variant),
+    WherePredicate(ast::WherePredicate),
     Crate(ast::Crate),
 }
 
@@ -71,6 +72,7 @@ impl Annotatable {
             Annotatable::Param(p) => p.span,
             Annotatable::FieldDef(sf) => sf.span,
             Annotatable::Variant(v) => v.span,
+            Annotatable::WherePredicate(wp) => wp.span,
             Annotatable::Crate(c) => c.spans.inner_span,
         }
     }
@@ -89,6 +91,7 @@ impl Annotatable {
             Annotatable::Param(p) => p.visit_attrs(f),
             Annotatable::FieldDef(sf) => sf.visit_attrs(f),
             Annotatable::Variant(v) => v.visit_attrs(f),
+            Annotatable::WherePredicate(wp) => wp.visit_attrs(f),
             Annotatable::Crate(c) => c.visit_attrs(f),
         }
     }
@@ -107,6 +110,7 @@ impl Annotatable {
             Annotatable::Param(p) => visitor.visit_param(p),
             Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
             Annotatable::Variant(v) => visitor.visit_variant(v),
+            Annotatable::WherePredicate(wp) => visitor.visit_where_predicate(wp),
             Annotatable::Crate(c) => visitor.visit_crate(c),
         }
     }
@@ -128,6 +132,7 @@ impl Annotatable {
             | Annotatable::Param(..)
             | Annotatable::FieldDef(..)
             | Annotatable::Variant(..)
+            | Annotatable::WherePredicate(..)
             | Annotatable::Crate(..) => panic!("unexpected annotatable"),
         }
     }
@@ -223,6 +228,13 @@ impl Annotatable {
         }
     }
 
+    pub fn expect_where_predicate(self) -> ast::WherePredicate {
+        match self {
+            Annotatable::WherePredicate(wp) => wp,
+            _ => panic!("expected where predicate"),
+        }
+    }
+
     pub fn expect_crate(self) -> ast::Crate {
         match self {
             Annotatable::Crate(krate) => krate,
@@ -446,6 +458,10 @@ pub trait MacResult {
         None
     }
 
+    fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
+        None
+    }
+
     fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
         // Fn-like macros cannot produce a crate.
         unreachable!()
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 83255b82017..5570c0c38e8 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -328,7 +328,7 @@ impl<'a> StripUnconfigured<'a> {
 
         // For inner attributes, we do the same thing for the `!` in `#![attr]`.
         let mut trees = if cfg_attr.style == AttrStyle::Inner {
-            let Some(TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _)) =
+            let Some(TokenTree::Token(bang_token @ Token { kind: TokenKind::Bang, .. }, _)) =
                 orig_trees.next()
             else {
                 panic!("Bad tokens for attribute {cfg_attr:?}");
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index e3f31ebeca3..c523bcece72 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -227,6 +227,12 @@ ast_fragments! {
     Variants(SmallVec<[ast::Variant; 1]>) {
         "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
     }
+    WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
+        "where predicate";
+        many fn flat_map_where_predicate;
+        fn visit_where_predicate();
+        fn make_where_predicates;
+     }
     Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
 }
 
@@ -259,7 +265,8 @@ impl AstFragmentKind {
             | AstFragmentKind::GenericParams
             | AstFragmentKind::Params
             | AstFragmentKind::FieldDefs
-            | AstFragmentKind::Variants => SupportsMacroExpansion::No,
+            | AstFragmentKind::Variants
+            | AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,
         }
     }
 
@@ -290,6 +297,9 @@ impl AstFragmentKind {
             AstFragmentKind::Variants => {
                 AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
             }
+            AstFragmentKind::WherePredicates => AstFragment::WherePredicates(
+                items.map(Annotatable::expect_where_predicate).collect(),
+            ),
             AstFragmentKind::Items => {
                 AstFragment::Items(items.map(Annotatable::expect_item).collect())
             }
@@ -865,7 +875,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             | Annotatable::GenericParam(..)
             | Annotatable::Param(..)
             | Annotatable::FieldDef(..)
-            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
+            | Annotatable::Variant(..)
+            | Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),
         };
         if self.cx.ecfg.features.proc_macro_hygiene() {
             return;
@@ -1002,7 +1013,8 @@ pub fn parse_ast_fragment<'a>(
         | AstFragmentKind::GenericParams
         | AstFragmentKind::Params
         | AstFragmentKind::FieldDefs
-        | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
+        | AstFragmentKind::Variants
+        | AstFragmentKind::WherePredicates => panic!("unexpected AST fragment kind"),
     })
 }
 
@@ -1414,6 +1426,19 @@ impl InvocationCollectorNode for ast::Variant {
     }
 }
 
+impl InvocationCollectorNode for ast::WherePredicate {
+    const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;
+    fn to_annotatable(self) -> Annotatable {
+        Annotatable::WherePredicate(self)
+    }
+    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
+        fragment.make_where_predicates()
+    }
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_where_predicate(visitor, self)
+    }
+}
+
 impl InvocationCollectorNode for ast::FieldDef {
     const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;
     fn to_annotatable(self) -> Annotatable {
@@ -2116,6 +2141,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         self.flat_map_node(node)
     }
 
+    fn flat_map_where_predicate(
+        &mut self,
+        node: ast::WherePredicate,
+    ) -> SmallVec<[ast::WherePredicate; 1]> {
+        self.flat_map_node(node)
+    }
+
     fn flat_map_field_def(&mut self, node: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
         self.flat_map_node(node)
     }
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 729dec2bfbd..1a2db233b7a 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -432,7 +432,7 @@ fn check_nested_occurrences(
             }
             (
                 NestedMacroState::MacroRules,
-                &TokenTree::Token(Token { kind: TokenKind::Not, .. }),
+                &TokenTree::Token(Token { kind: TokenKind::Bang, .. }),
             ) => {
                 state = NestedMacroState::MacroRulesNot;
             }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index cc7e3e65105..5577c8902da 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -690,7 +690,7 @@ fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
                     && let TokenKind::Ident(ident, _) = ident.kind
                     && ident == sym::compile_error
                     && let mbe::TokenTree::Token(bang) = bang
-                    && let TokenKind::Not = bang.kind
+                    && let TokenKind::Bang = bang.kind
                     && let mbe::TokenTree::Delimited(.., del) = args
                     && !del.delim.skip()
                 {
@@ -1135,7 +1135,7 @@ fn check_matcher_core<'tt>(
                         && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
                         && matches!(
                             next_token,
-                            TokenTree::Token(token) if *token == BinOp(token::BinOpToken::Or)
+                            TokenTree::Token(token) if *token == token::Or
                         )
                     {
                         // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
@@ -1177,7 +1177,7 @@ fn check_matcher_core<'tt>(
 
                             if kind == NonterminalKind::Pat(PatWithOr)
                                 && sess.psess.edition.at_least_rust_2021()
-                                && next_token.is_token(&BinOp(token::BinOpToken::Or))
+                                && next_token.is_token(&token::Or)
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
                                     span,
@@ -1296,7 +1296,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
-                        FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes,
+                        FatArrow | Comma | Eq | Or => IsInFollow::Yes,
                         Ident(name, IdentIsRaw::No) if name == kw::If || name == kw::In => {
                             IsInFollow::Yes
                         }
@@ -1332,9 +1332,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                         | Colon
                         | Eq
                         | Gt
-                        | BinOp(token::Shr)
+                        | Shr
                         | Semi
-                        | BinOp(token::Or) => IsInFollow::Yes,
+                        | Or => IsInFollow::Yes,
                         Ident(name, IdentIsRaw::No) if name == kw::As || name == kw::Where => {
                             IsInFollow::Yes
                         }
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index b9a06157907..8cb001391c5 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -302,8 +302,8 @@ fn parse_tree<'a>(
 /// `None`.
 fn kleene_op(token: &Token) -> Option<KleeneOp> {
     match token.kind {
-        token::BinOp(token::Star) => Some(KleeneOp::ZeroOrMore),
-        token::BinOp(token::Plus) => Some(KleeneOp::OneOrMore),
+        token::Star => Some(KleeneOp::ZeroOrMore),
+        token::Plus => Some(KleeneOp::OneOrMore),
         token::Question => Some(KleeneOp::ZeroOrOne),
         _ => None,
     }
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index e969f2d4fb5..3a470924c7f 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -188,6 +188,19 @@ pub(crate) fn placeholder(
             vis,
             is_placeholder: true,
         }]),
+        AstFragmentKind::WherePredicates => {
+            AstFragment::WherePredicates(smallvec![ast::WherePredicate {
+                attrs: Default::default(),
+                id,
+                span,
+                kind: ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
+                    bound_generic_params: Default::default(),
+                    bounded_ty: ty(),
+                    bounds: Default::default(),
+                }),
+                is_placeholder: true,
+            }])
+        }
     }
 }
 
@@ -267,6 +280,17 @@ impl MutVisitor for PlaceholderExpander {
         }
     }
 
+    fn flat_map_where_predicate(
+        &mut self,
+        predicate: ast::WherePredicate,
+    ) -> SmallVec<[ast::WherePredicate; 1]> {
+        if predicate.is_placeholder {
+            self.remove(predicate.id).make_where_predicates()
+        } else {
+            walk_flat_map_where_predicate(self, predicate)
+        }
+    }
+
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
             ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 5581a6e6508..007241437ec 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -180,28 +180,28 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                 Gt => op(">"),
                 AndAnd => op("&&"),
                 OrOr => op("||"),
-                Not => op("!"),
+                Bang => op("!"),
                 Tilde => op("~"),
-                BinOp(Plus) => op("+"),
-                BinOp(Minus) => op("-"),
-                BinOp(Star) => op("*"),
-                BinOp(Slash) => op("/"),
-                BinOp(Percent) => op("%"),
-                BinOp(Caret) => op("^"),
-                BinOp(And) => op("&"),
-                BinOp(Or) => op("|"),
-                BinOp(Shl) => op("<<"),
-                BinOp(Shr) => op(">>"),
-                BinOpEq(Plus) => op("+="),
-                BinOpEq(Minus) => op("-="),
-                BinOpEq(Star) => op("*="),
-                BinOpEq(Slash) => op("/="),
-                BinOpEq(Percent) => op("%="),
-                BinOpEq(Caret) => op("^="),
-                BinOpEq(And) => op("&="),
-                BinOpEq(Or) => op("|="),
-                BinOpEq(Shl) => op("<<="),
-                BinOpEq(Shr) => op(">>="),
+                Plus => op("+"),
+                Minus => op("-"),
+                Star => op("*"),
+                Slash => op("/"),
+                Percent => op("%"),
+                Caret => op("^"),
+                And => op("&"),
+                Or => op("|"),
+                Shl => op("<<"),
+                Shr => op(">>"),
+                PlusEq => op("+="),
+                MinusEq => op("-="),
+                StarEq => op("*="),
+                SlashEq => op("/="),
+                PercentEq => op("%="),
+                CaretEq => op("^="),
+                AndEq => op("&="),
+                OrEq => op("|="),
+                ShlEq => op("<<="),
+                ShrEq => op(">>="),
                 At => op("@"),
                 Dot => op("."),
                 DotDot => op(".."),
@@ -322,16 +322,16 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                     b'=' => Eq,
                     b'<' => Lt,
                     b'>' => Gt,
-                    b'!' => Not,
+                    b'!' => Bang,
                     b'~' => Tilde,
-                    b'+' => BinOp(Plus),
-                    b'-' => BinOp(Minus),
-                    b'*' => BinOp(Star),
-                    b'/' => BinOp(Slash),
-                    b'%' => BinOp(Percent),
-                    b'^' => BinOp(Caret),
-                    b'&' => BinOp(And),
-                    b'|' => BinOp(Or),
+                    b'+' => Plus,
+                    b'-' => Minus,
+                    b'*' => Star,
+                    b'/' => Slash,
+                    b'%' => Percent,
+                    b'^' => Caret,
+                    b'&' => And,
+                    b'|' => Or,
                     b'@' => At,
                     b'.' => Dot,
                     b',' => Comma,
@@ -372,10 +372,9 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                 suffix,
                 span,
             }) if symbol.as_str().starts_with('-') => {
-                let minus = BinOp(BinOpToken::Minus);
                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
                 let integer = TokenKind::lit(token::Integer, symbol, suffix);
-                let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
+                let a = tokenstream::TokenTree::token_joint_hidden(Minus, span);
                 let b = tokenstream::TokenTree::token_alone(integer, span);
                 smallvec![a, b]
             }
@@ -385,10 +384,9 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                 suffix,
                 span,
             }) if symbol.as_str().starts_with('-') => {
-                let minus = BinOp(BinOpToken::Minus);
                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
                 let float = TokenKind::lit(token::Float, symbol, suffix);
-                let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
+                let a = tokenstream::TokenTree::token_joint_hidden(Minus, span);
                 let b = tokenstream::TokenTree::token_alone(float, span);
                 smallvec![a, b]
             }
@@ -599,10 +597,7 @@ impl server::TokenStream for Rustc<'_, '_> {
                         Ok(Self::TokenStream::from_iter([
                             // FIXME: The span of the `-` token is lost when
                             // parsing, so we cannot faithfully recover it here.
-                            tokenstream::TokenTree::token_joint_hidden(
-                                token::BinOp(token::Minus),
-                                e.span,
-                            ),
+                            tokenstream::TokenTree::token_joint_hidden(token::Minus, e.span),
                             tokenstream::TokenTree::token_alone(token::Literal(*token_lit), e.span),
                         ]))
                     }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 306535bf764..40857e0066e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -576,6 +576,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
     ),
 
+    // Probably temporary component of min_generic_const_args.
+    // `#[type_const] const ASSOC: usize;`
+    gated!(
+        type_const, Normal, template!(Word), ErrorFollowing,
+        EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
+    ),
+
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index fc58b66ad35..47e4f9a2fe8 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -244,6 +244,8 @@ declare_features! (
     /// Allows unnamed fields of struct and union type
     (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")),
     (removed, unsafe_no_drop_flag, "1.0.0", None, None),
+    (removed, unsized_tuple_coercion, "CURRENT_RUSTC_VERSION", Some(42877),
+     Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")),
     /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
     (removed, untagged_unions, "1.13.0", Some(55149),
      Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 0acd3b0f800..b39ad8875a4 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -601,6 +601,8 @@ declare_features! (
     (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
+    /// Allows the use of raw-dylibs on ELF platforms
+    (incomplete, raw_dylib_elf, "CURRENT_RUSTC_VERSION", Some(135694)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
     (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant
@@ -657,10 +659,10 @@ declare_features! (
     (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
     (incomplete, unsized_locals, "1.30.0", Some(48055)),
-    /// Allows unsized tuple coercion.
-    (unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
+    /// Allows use of attributes in `where` clauses.
+    (unstable, where_clause_attrs, "CURRENT_RUSTC_VERSION", Some(115590)),
     /// Allows use of x86 `AMX` target-feature attributes and intrinsics
     (unstable, x86_amx_intrinsics, "1.81.0", Some(126622)),
     /// Allows use of the `xop` target-feature
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 70e95a84e68..601898023fc 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -56,6 +56,7 @@ pub enum Target {
     Param,
     PatField,
     ExprField,
+    WherePredicate,
 }
 
 impl Display for Target {
@@ -96,7 +97,8 @@ impl Target {
             | Target::MacroDef
             | Target::Param
             | Target::PatField
-            | Target::ExprField => false,
+            | Target::ExprField
+            | Target::WherePredicate => false,
         }
     }
 
@@ -217,6 +219,7 @@ impl Target {
             Target::Param => "function param",
             Target::PatField => "pattern field",
             Target::ExprField => "struct field",
+            Target::WherePredicate => "where predicate",
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index f2331f3fd8e..f89f41aaf8a 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -745,14 +745,10 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     match tcx.def_kind(def_id) {
         DefKind::Static { .. } => {
-            tcx.ensure_ok().typeck(def_id);
-            maybe_check_static_with_link_section(tcx, def_id);
             check_static_inhabited(tcx, def_id);
             check_static_linkage(tcx, def_id);
         }
-        DefKind::Const => {
-            tcx.ensure_ok().typeck(def_id);
-        }
+        DefKind::Const => {}
         DefKind::Enum => {
             check_enum(tcx, def_id);
         }
@@ -766,7 +762,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                     ExternAbi::Rust,
                 )
             }
-            // Everything else is checked entirely within check_item_body
         }
         DefKind::Impl { of_trait } => {
             if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 1c5455710db..89a759f7dda 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -145,7 +145,7 @@ pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) {
     }
 }
 
-fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
+pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
     // Only restricted on wasm target for now
     if !tcx.sess.target.is_like_wasm {
         return;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d72cf00293f..a400aaa8142 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -126,13 +126,14 @@ where
 
     let infcx_compat = infcx.fork();
 
-    // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always.
+    // We specifically want to *disable* the implied bounds hack, first,
+    // so we can detect when failures are due to bevy's implied bounds.
     let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
         &infcx,
         body_def_id,
         param_env,
         assumed_wf_types.iter().copied(),
-        false,
+        true,
     );
 
     lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);
@@ -142,53 +143,22 @@ where
         return Ok(());
     }
 
-    let is_bevy = assumed_wf_types.visit_with(&mut ContainsBevyParamSet { tcx }).is_break();
-
-    // If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
-    // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
-    // but that does result in slightly more work when this option is set and
-    // just obscures what we mean here anyways. Let's just be explicit.
-    if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
-        let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
-            &infcx,
-            body_def_id,
-            param_env,
-            assumed_wf_types,
-            true,
-        );
-        let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
-        if errors_compat.is_empty() {
-            Ok(())
-        } else {
-            Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
-        }
+    let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
+        &infcx_compat,
+        body_def_id,
+        param_env,
+        assumed_wf_types,
+        // Don't *disable* the implied bounds hack; though this will only apply
+        // the implied bounds hack if this contains `bevy_ecs`'s `ParamSet` type.
+        false,
+    );
+    let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
+    if errors_compat.is_empty() {
+        // FIXME: Once we fix bevy, this would be the place to insert a warning
+        // to upgrade bevy.
+        Ok(())
     } else {
-        Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors))
-    }
-}
-
-struct ContainsBevyParamSet<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> {
-    type Result = ControlFlow<()>;
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
-        // We only care to match `ParamSet<T>` or `&ParamSet<T>`.
-        match t.kind() {
-            ty::Adt(def, _) => {
-                if self.tcx.item_name(def.did()) == sym::ParamSet
-                    && self.tcx.crate_name(def.did().krate) == sym::bevy_ecs
-                {
-                    return ControlFlow::Break(());
-                }
-            }
-            ty::Ref(_, ty, _) => ty.visit_with(self)?,
-            _ => {}
-        }
-
-        ControlFlow::Continue(())
+        Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
     }
 }
 
@@ -201,7 +171,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
         hir::Node::ImplItem(item) => check_impl_item(tcx, item),
         hir::Node::ForeignItem(item) => check_foreign_item(tcx, item),
         hir::Node::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)),
-        _ => unreachable!(),
+        _ => unreachable!("{node:?}"),
     };
 
     if let Some(generics) = node.generics() {
@@ -1108,7 +1078,13 @@ fn check_associated_item(
                 let ty = tcx.type_of(item.def_id).instantiate_identity();
                 let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                 wfcx.register_wf_obligation(span, loc, ty.into());
-                check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span));
+                check_sized_if_body(
+                    wfcx,
+                    item.def_id.expect_local(),
+                    ty,
+                    Some(span),
+                    ObligationCauseCode::SizedConstOrStatic,
+                );
                 Ok(())
             }
             ty::AssocKind::Fn => {
@@ -1354,7 +1330,7 @@ fn check_item_type(
                 traits::ObligationCause::new(
                     ty_span,
                     wfcx.body_def_id,
-                    ObligationCauseCode::WellFormed(None),
+                    ObligationCauseCode::SizedConstOrStatic,
                 ),
                 wfcx.param_env,
                 item_ty,
@@ -1698,6 +1674,7 @@ fn check_fn_or_method<'tcx>(
             hir::FnRetTy::Return(ty) => Some(ty.span),
             hir::FnRetTy::DefaultReturn(_) => None,
         },
+        ObligationCauseCode::SizedReturnType,
     );
 }
 
@@ -1706,13 +1683,14 @@ fn check_sized_if_body<'tcx>(
     def_id: LocalDefId,
     ty: Ty<'tcx>,
     maybe_span: Option<Span>,
+    code: ObligationCauseCode<'tcx>,
 ) {
     let tcx = wfcx.tcx();
     if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {
         let span = maybe_span.unwrap_or(body.value.span);
 
         wfcx.register_bound(
-            ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType),
+            ObligationCause::new(span, def_id, code),
             wfcx.param_env,
             ty,
             tcx.require_lang_item(LangItem::Sized, Some(span)),
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 027aa5554a4..49523912b14 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -45,6 +45,7 @@ use tracing::{debug, instrument};
 
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
+use crate::hir_ty_lowering::errors::assoc_kind_str;
 use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
 
 pub(crate) mod dump;
@@ -443,13 +444,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
         self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
     }
 
-    fn lower_assoc_ty(
+    fn lower_assoc_shared(
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'tcx>,
+        item_segment: &rustc_hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Ty<'tcx> {
+        kind: ty::AssocKind,
+    ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
             let item_args = self.lowerer().lower_generic_args_of_assoc_item(
                 span,
@@ -457,7 +459,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                 item_segment,
                 trait_ref.args,
             );
-            Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
+            Ok((item_def_id, item_args))
         } else {
             // There are no late-bound regions; we can just ignore the binder.
             let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -518,16 +520,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                 }
                 _ => {}
             }
-            Ty::new_error(
-                self.tcx(),
-                self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
-                    span,
-                    inferred_sugg,
-                    bound,
-                    mpart_sugg,
-                    what: "type",
-                }),
-            )
+
+            Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
+                span,
+                inferred_sugg,
+                bound,
+                mpart_sugg,
+                what: assoc_kind_str(kind),
+            }))
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index af1338e50d0..a153ce8ea90 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -187,6 +187,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                         Some(parent_did)
                     }
                     Node::TyPat(_) => Some(parent_did),
+                    // Field default values inherit the ADT's generics.
+                    Node::Field(_) => Some(parent_did),
                     _ => None,
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index dd346ed1f97..60af36da6e2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -468,11 +468,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
                 // Good error for `where Trait::method(..): Send`.
                 let Some(self_ty) = opt_self_ty else {
-                    return self.error_missing_qpath_self_ty(
+                    let guar = self.error_missing_qpath_self_ty(
                         trait_def_id,
                         hir_ty.span,
                         item_segment,
+                        ty::AssocKind::Type,
                     );
+                    return Ty::new_error(tcx, guar);
                 };
                 let self_ty = self.lower_ty(self_ty);
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 922578792ba..d51fd7f7e78 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -385,14 +385,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         })
     }
 
-    pub(super) fn report_ambiguous_assoc_ty(
+    pub(super) fn report_ambiguous_assoc(
         &self,
         span: Span,
         types: &[String],
         traits: &[String],
         name: Symbol,
+        kind: ty::AssocKind,
     ) -> ErrorGuaranteed {
-        let mut err = struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type");
+        let kind_str = assoc_kind_str(kind);
+        let mut err =
+            struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
         if self
             .tcx()
             .resolutions(())
@@ -417,7 +420,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         span,
                         format!(
                             "if there were a type named `Type` that implements a trait named \
-                             `Trait` with associated type `{name}`, you could use the \
+                             `Trait` with associated {kind_str} `{name}`, you could use the \
                              fully-qualified path",
                         ),
                         format!("<Type as Trait>::{name}"),
@@ -440,7 +443,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         span,
                         format!(
                             "if there were a type named `Example` that implemented one of the \
-                             traits with associated type `{name}`, you could use the \
+                             traits with associated {kind_str} `{name}`, you could use the \
                              fully-qualified path",
                         ),
                         traits.iter().map(|trait_str| format!("<Example as {trait_str}>::{name}")),
@@ -451,7 +454,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     err.span_suggestion_verbose(
                         span,
                         format!(
-                            "if there were a trait named `Example` with associated type `{name}` \
+                            "if there were a trait named `Example` with associated {kind_str} `{name}` \
                              implemented for `{type_str}`, you could use the fully-qualified path",
                         ),
                         format!("<{type_str} as Example>::{name}"),
@@ -462,7 +465,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     err.span_suggestions(
                         span,
                         format!(
-                            "if there were a trait named `Example` with associated type `{name}` \
+                            "if there were a trait named `Example` with associated {kind_str} `{name}` \
                              implemented for one of the types, you could use the fully-qualified \
                              path",
                         ),
@@ -491,7 +494,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         err.emit()
     }
 
-    pub(crate) fn complain_about_ambiguous_inherent_assoc_ty(
+    pub(crate) fn complain_about_ambiguous_inherent_assoc(
         &self,
         name: Ident,
         candidates: Vec<DefId>,
@@ -552,13 +555,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     }
 
     // FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
-    pub(crate) fn complain_about_inherent_assoc_ty_not_found(
+    pub(crate) fn complain_about_inherent_assoc_not_found(
         &self,
         name: Ident,
         self_ty: Ty<'tcx>,
         candidates: Vec<(DefId, (DefId, DefId))>,
         fulfillment_errors: Vec<FulfillmentError<'tcx>>,
         span: Span,
+        kind: ty::AssocKind,
     ) -> ErrorGuaranteed {
         // FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
         // Either
@@ -568,12 +572,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         let tcx = self.tcx();
 
+        let kind_str = assoc_kind_str(kind);
         let adt_did = self_ty.ty_adt_def().map(|def| def.did());
         let add_def_label = |err: &mut Diag<'_>| {
             if let Some(did) = adt_did {
                 err.span_label(
                     tcx.def_span(did),
-                    format!("associated item `{name}` not found for this {}", tcx.def_descr(did)),
+                    format!(
+                        "associated {kind_str} `{name}` not found for this {}",
+                        tcx.def_descr(did)
+                    ),
                 );
             }
         };
@@ -600,11 +608,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 self.dcx(),
                 name.span,
                 E0220,
-                "associated type `{name}` not found for `{self_ty}` in the current scope"
+                "associated {kind_str} `{name}` not found for `{self_ty}` in the current scope"
             );
             err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
             err.note(format!(
-                "the associated type was found for\n{type_candidates}{additional_types}",
+                "the associated {kind_str} was found for\n{type_candidates}{additional_types}",
             ));
             add_def_label(&mut err);
             return err.emit();
@@ -685,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         let mut err = self.dcx().struct_span_err(
             name.span,
-            format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
+            format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
         );
         if !bounds.is_empty() {
             err.note(format!(
@@ -695,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
         err.span_label(
             name.span,
-            format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
+            format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
         );
 
         for (span, mut bounds) in bound_spans {
@@ -1614,7 +1622,7 @@ fn generics_args_err_extend<'a>(
     }
 }
 
-pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
+pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
     match kind {
         ty::AssocKind::Fn => "function",
         ty::AssocKind::Const => "constant",
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index fa58f12c553..60a60f6415a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -115,7 +115,7 @@ fn generic_arg_mismatch_err(
                     body.value.kind
                 && let Res::Def(DefKind::Fn { .. }, id) = path.res
             {
-                // FIXME(min_generic_const_args): this branch is dead once new const path lowering
+                // FIXME(mgca): this branch is dead once new const path lowering
                 // (for single-segment paths) is no longer gated
                 err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
                 err.help("function item types cannot be named directly");
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a0f848f07c4..d044688246f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -44,14 +44,16 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc_session::parse::feature_err;
 use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
+use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 use rustc_type_ir::Upcast;
 use tracing::{debug, instrument};
 
+use self::errors::assoc_kind_str;
 use crate::check::check_abi_fn_ptr;
 use crate::errors::{
     AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed,
@@ -152,7 +154,7 @@ pub trait HirTyLowerer<'tcx> {
         assoc_name: Ident,
     ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>;
 
-    /// Lower an associated type to a projection.
+    /// Lower an associated type/const (from a trait) to a projection.
     ///
     /// This method has to be defined by the concrete lowering context because
     /// dealing with higher-ranked trait references depends on its capabilities:
@@ -164,13 +166,14 @@ pub trait HirTyLowerer<'tcx> {
     ///
     /// The canonical example of this is associated type `T::P` where `T` is a type
     /// param constrained by `T: for<'a> Trait<'a>` and where `Trait` defines `P`.
-    fn lower_assoc_ty(
+    fn lower_assoc_shared(
         &self,
         span: Span,
         item_def_id: DefId,
         item_segment: &hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Ty<'tcx>;
+        kind: ty::AssocKind,
+    ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;
 
     fn lower_fn_sig(
         &self,
@@ -245,6 +248,42 @@ pub enum FeedConstTy<'a, 'tcx> {
     No,
 }
 
+#[derive(Debug, Clone, Copy)]
+enum LowerAssocMode {
+    Type { permit_variants: bool },
+    Const,
+}
+
+impl LowerAssocMode {
+    fn kind(self) -> ty::AssocKind {
+        match self {
+            LowerAssocMode::Type { .. } => ty::AssocKind::Type,
+            LowerAssocMode::Const => ty::AssocKind::Const,
+        }
+    }
+
+    fn def_kind(self) -> DefKind {
+        match self {
+            LowerAssocMode::Type { .. } => DefKind::AssocTy,
+            LowerAssocMode::Const => DefKind::AssocConst,
+        }
+    }
+
+    fn permit_variants(self) -> bool {
+        match self {
+            LowerAssocMode::Type { permit_variants } => permit_variants,
+            // FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which resolve to const ctors/fn items respectively
+            LowerAssocMode::Const => false,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+enum LoweredAssoc<'tcx> {
+    Term(DefId, GenericArgsRef<'tcx>),
+    Variant { adt: Ty<'tcx>, variant_did: DefId },
+}
+
 /// New-typed boolean indicating whether explicit late-bound lifetimes
 /// are present in a set of generic arguments.
 ///
@@ -630,7 +669,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         (args, arg_count)
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "debug", skip(self))]
     pub fn lower_generic_args_of_assoc_item(
         &self,
         span: Span,
@@ -638,7 +677,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         item_segment: &hir::PathSegment<'tcx>,
         parent_args: GenericArgsRef<'tcx>,
     ) -> GenericArgsRef<'tcx> {
-        debug!(?span, ?item_def_id, ?item_segment);
         let (args, _) =
             self.lower_generic_args_of_path(span, item_def_id, parent_args, item_segment, None);
         if let Some(c) = item_segment.args().constraints.first() {
@@ -1118,7 +1156,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     // NOTE: When this function starts resolving `Trait::AssocTy` successfully
     // it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
     #[instrument(level = "debug", skip_all, ret)]
-    pub fn lower_assoc_path(
+    pub fn lower_assoc_path_ty(
         &self,
         hir_ref_id: HirId,
         span: Span,
@@ -1127,6 +1165,72 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         assoc_segment: &'tcx hir::PathSegment<'tcx>,
         permit_variants: bool,
     ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
+        let tcx = self.tcx();
+        match self.lower_assoc_path_shared(
+            hir_ref_id,
+            span,
+            qself_ty,
+            qself,
+            assoc_segment,
+            LowerAssocMode::Type { permit_variants },
+        )? {
+            LoweredAssoc::Term(def_id, args) => {
+                let alias_ty = ty::AliasTy::new_from_args(tcx, def_id, args);
+                let ty = Ty::new_alias(tcx, alias_ty.kind(tcx), alias_ty);
+                Ok((ty, tcx.def_kind(def_id), def_id))
+            }
+            LoweredAssoc::Variant { adt, variant_did } => Ok((adt, DefKind::Variant, variant_did)),
+        }
+    }
+
+    #[instrument(level = "debug", skip_all, ret)]
+    fn lower_assoc_path_const(
+        &self,
+        hir_ref_id: HirId,
+        span: Span,
+        qself_ty: Ty<'tcx>,
+        qself: &'tcx hir::Ty<'tcx>,
+        assoc_segment: &'tcx hir::PathSegment<'tcx>,
+    ) -> Result<Const<'tcx>, ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let (def_id, args) = match self.lower_assoc_path_shared(
+            hir_ref_id,
+            span,
+            qself_ty,
+            qself,
+            assoc_segment,
+            LowerAssocMode::Const,
+        )? {
+            LoweredAssoc::Term(def_id, args) => {
+                if !tcx.associated_item(def_id).is_type_const_capable(tcx) {
+                    let mut err = tcx.dcx().struct_span_err(
+                        span,
+                        "use of trait associated const without `#[type_const]`",
+                    );
+                    err.note("the declaration in the trait must be marked with `#[type_const]`");
+                    return Err(err.emit());
+                }
+                (def_id, args)
+            }
+            // FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
+            // not just const ctors
+            LoweredAssoc::Variant { .. } => {
+                span_bug!(span, "unexpected variant res for type associated const path")
+            }
+        };
+        Ok(Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)))
+    }
+
+    #[instrument(level = "debug", skip_all, ret)]
+    fn lower_assoc_path_shared(
+        &self,
+        hir_ref_id: HirId,
+        span: Span,
+        qself_ty: Ty<'tcx>,
+        qself: &'tcx hir::Ty<'tcx>,
+        assoc_segment: &'tcx hir::PathSegment<'tcx>,
+        mode: LowerAssocMode,
+    ) -> Result<LoweredAssoc<'tcx>, ErrorGuaranteed> {
         debug!(%qself_ty, ?assoc_segment.ident);
         let tcx = self.tcx();
 
@@ -1141,13 +1245,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     .iter()
                     .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident(tcx), adt_def.did()));
                 if let Some(variant_def) = variant_def {
-                    if permit_variants {
+                    if mode.permit_variants() {
                         tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
                         let _ = self.prohibit_generic_args(
                             slice::from_ref(assoc_segment).iter(),
                             GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
                         );
-                        return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
+                        return Ok(LoweredAssoc::Variant {
+                            adt: qself_ty,
+                            variant_did: variant_def.def_id,
+                        });
                     } else {
                         variant_resolution = Some(variant_def.def_id);
                     }
@@ -1155,15 +1262,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
 
             // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
-            if let Some((ty, did)) = self.probe_inherent_assoc_ty(
-                assoc_ident,
+            if let Some((did, args)) = self.probe_inherent_assoc_shared(
                 assoc_segment,
                 adt_def.did(),
                 qself_ty,
                 hir_ref_id,
                 span,
+                mode.kind(),
             )? {
-                return Ok((ty, DefKind::AssocTy, did));
+                return Ok(LoweredAssoc::Term(did, args));
             }
         }
 
@@ -1192,7 +1299,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         )
                     },
                     AssocItemQSelf::SelfTyAlias,
-                    ty::AssocKind::Type,
+                    mode.kind(),
                     assoc_ident,
                     span,
                     None,
@@ -1204,14 +1311,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ) => self.probe_single_ty_param_bound_for_assoc_item(
                 param_did.expect_local(),
                 qself.span,
-                ty::AssocKind::Type,
+                mode.kind(),
                 assoc_ident,
                 span,
             )?,
             _ => {
+                let kind_str = assoc_kind_str(mode.kind());
                 let reported = if variant_resolution.is_some() {
                     // Variant in type position
-                    let msg = format!("expected type, found variant `{assoc_ident}`");
+                    let msg = format!("expected {kind_str}, found variant `{assoc_ident}`");
                     self.dcx().span_err(span, msg)
                 } else if qself_ty.is_enum() {
                     let mut err = self.dcx().create_err(NoVariantNamed {
@@ -1310,11 +1418,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
 
                     // Don't print `ty::Error` to the user.
-                    self.report_ambiguous_assoc_ty(
+                    self.report_ambiguous_assoc(
                         span,
                         &[qself_ty.to_string()],
                         &traits,
                         assoc_ident.name,
+                        mode.kind(),
                     )
                 };
                 return Err(reported);
@@ -1322,10 +1431,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         };
 
         let trait_did = bound.def_id();
-        let assoc_ty = self
-            .probe_assoc_item(assoc_ident, ty::AssocKind::Type, hir_ref_id, span, trait_did)
-            .expect("failed to find associated type");
-        let ty = self.lower_assoc_ty(span, assoc_ty.def_id, assoc_segment, bound);
+        let assoc_item = self
+            .probe_assoc_item(assoc_ident, mode.kind(), hir_ref_id, span, trait_did)
+            .expect("failed to find associated item");
+        let (def_id, args) =
+            self.lower_assoc_shared(span, assoc_item.def_id, assoc_segment, bound, mode.kind())?;
+        let result = LoweredAssoc::Term(def_id, args);
 
         if let Some(variant_def_id) = variant_resolution {
             tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
@@ -1341,7 +1452,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 };
 
                 could_refer_to(DefKind::Variant, variant_def_id, "");
-                could_refer_to(DefKind::AssocTy, assoc_ty.def_id, " also");
+                could_refer_to(mode.def_kind(), assoc_item.def_id, " also");
 
                 lint.span_suggestion(
                     span,
@@ -1351,36 +1462,51 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 );
             });
         }
-        Ok((ty, DefKind::AssocTy, assoc_ty.def_id))
+        Ok(result)
     }
 
-    fn probe_inherent_assoc_ty(
+    fn probe_inherent_assoc_shared(
         &self,
-        name: Ident,
         segment: &hir::PathSegment<'tcx>,
         adt_did: DefId,
         self_ty: Ty<'tcx>,
         block: HirId,
         span: Span,
-    ) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
+        kind: ty::AssocKind,
+    ) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
         let tcx = self.tcx();
 
-        // Don't attempt to look up inherent associated types when the feature is not enabled.
-        // Theoretically it'd be fine to do so since we feature-gate their definition site.
-        // However, due to current limitations of the implementation (caused by us performing
-        // selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
-        // errors (#108491) which mask the feature-gate error, needlessly confusing users
-        // who use IATs by accident (#113265).
         if !tcx.features().inherent_associated_types() {
-            return Ok(None);
+            match kind {
+                // Don't attempt to look up inherent associated types when the feature is not enabled.
+                // Theoretically it'd be fine to do so since we feature-gate their definition site.
+                // However, due to current limitations of the implementation (caused by us performing
+                // selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
+                // errors (#108491) which mask the feature-gate error, needlessly confusing users
+                // who use IATs by accident (#113265).
+                ty::AssocKind::Type => return Ok(None),
+                ty::AssocKind::Const => {
+                    // We also gate the mgca codepath for type-level uses of inherent consts
+                    // with the inherent_associated_types feature gate since it relies on the
+                    // same machinery and has similar rough edges.
+                    return Err(feature_err(
+                        &tcx.sess,
+                        sym::inherent_associated_types,
+                        span,
+                        "inherent associated types are unstable",
+                    )
+                    .emit());
+                }
+                ty::AssocKind::Fn => unreachable!(),
+            }
         }
 
+        let name = segment.ident;
         let candidates: Vec<_> = tcx
             .inherent_impls(adt_did)
             .iter()
             .filter_map(|&impl_| {
-                let (item, scope) =
-                    self.probe_assoc_item_unchecked(name, ty::AssocKind::Type, block, impl_)?;
+                let (item, scope) = self.probe_assoc_item_unchecked(name, kind, block, impl_)?;
                 Some((impl_, (item.def_id, scope)))
             })
             .collect();
@@ -1395,13 +1521,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         // In contexts that have no inference context, just make a new one.
         // We do need a local variable to store it, though.
-        let infcx_;
         let infcx = match self.infcx() {
             Some(infcx) => infcx,
             None => {
                 assert!(!self_ty.has_infer());
-                infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
-                &infcx_
+                &tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis())
             }
         };
 
@@ -1420,8 +1544,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             &mut universes,
             self_ty,
             |self_ty| {
-                self.select_inherent_assoc_type_candidates(
-                    infcx, name, span, self_ty, param_env, candidates,
+                self.select_inherent_assoc_candidates(
+                    infcx, name, span, self_ty, param_env, candidates, kind,
                 )
             },
         )?;
@@ -1438,13 +1562,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 .chain(args.into_iter().skip(parent_args.len())),
         );
 
-        let ty =
-            Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
-
-        Ok(Some((ty, assoc_item)))
+        Ok(Some((assoc_item, args)))
     }
 
-    fn select_inherent_assoc_type_candidates(
+    fn select_inherent_assoc_candidates(
         &self,
         infcx: &InferCtxt<'tcx>,
         name: Ident,
@@ -1452,6 +1573,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         self_ty: Ty<'tcx>,
         param_env: ParamEnv<'tcx>,
         candidates: Vec<(DefId, (DefId, DefId))>,
+        kind: ty::AssocKind,
     ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
         let tcx = self.tcx();
         let mut fulfillment_errors = Vec::new();
@@ -1496,17 +1618,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .collect();
 
         match &applicable_candidates[..] {
-            &[] => Err(self.complain_about_inherent_assoc_ty_not_found(
+            &[] => Err(self.complain_about_inherent_assoc_not_found(
                 name,
                 self_ty,
                 candidates,
                 fulfillment_errors,
                 span,
+                kind,
             )),
 
             &[applicable_candidate] => Ok(applicable_candidate),
 
-            &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
+            &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
                 name,
                 applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
                 span,
@@ -1638,7 +1761,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
     /// Lower a qualified path to a type.
     #[instrument(level = "debug", skip_all)]
-    fn lower_qpath(
+    fn lower_qpath_ty(
         &self,
         span: Span,
         opt_self_ty: Option<Ty<'tcx>>,
@@ -1646,13 +1769,64 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         trait_segment: &hir::PathSegment<'tcx>,
         item_segment: &hir::PathSegment<'tcx>,
     ) -> Ty<'tcx> {
+        match self.lower_qpath_shared(
+            span,
+            opt_self_ty,
+            item_def_id,
+            trait_segment,
+            item_segment,
+            ty::AssocKind::Type,
+        ) {
+            Ok((item_def_id, item_args)) => {
+                Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
+            }
+            Err(guar) => Ty::new_error(self.tcx(), guar),
+        }
+    }
+
+    /// Lower a qualified path to a const.
+    #[instrument(level = "debug", skip_all)]
+    fn lower_qpath_const(
+        &self,
+        span: Span,
+        opt_self_ty: Option<Ty<'tcx>>,
+        item_def_id: DefId,
+        trait_segment: &hir::PathSegment<'tcx>,
+        item_segment: &hir::PathSegment<'tcx>,
+    ) -> Const<'tcx> {
+        match self.lower_qpath_shared(
+            span,
+            opt_self_ty,
+            item_def_id,
+            trait_segment,
+            item_segment,
+            ty::AssocKind::Const,
+        ) {
+            Ok((item_def_id, item_args)) => {
+                let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
+                Const::new_unevaluated(self.tcx(), uv)
+            }
+            Err(guar) => Const::new_error(self.tcx(), guar),
+        }
+    }
+
+    #[instrument(level = "debug", skip_all)]
+    fn lower_qpath_shared(
+        &self,
+        span: Span,
+        opt_self_ty: Option<Ty<'tcx>>,
+        item_def_id: DefId,
+        trait_segment: &hir::PathSegment<'tcx>,
+        item_segment: &hir::PathSegment<'tcx>,
+        kind: ty::AssocKind,
+    ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
         let tcx = self.tcx();
 
         let trait_def_id = tcx.parent(item_def_id);
         debug!(?trait_def_id);
 
         let Some(self_ty) = opt_self_ty else {
-            return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment);
+            return Err(self.error_missing_qpath_self_ty(trait_def_id, span, item_segment, kind));
         };
         debug!(?self_ty);
 
@@ -1663,7 +1837,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let item_args =
             self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
 
-        Ty::new_projection_from_args(tcx, item_def_id, item_args)
+        Ok((item_def_id, item_args))
     }
 
     fn error_missing_qpath_self_ty(
@@ -1671,7 +1845,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         trait_def_id: DefId,
         span: Span,
         item_segment: &hir::PathSegment<'tcx>,
-    ) -> Ty<'tcx> {
+        kind: ty::AssocKind,
+    ) -> ErrorGuaranteed {
         let tcx = self.tcx();
         let path_str = tcx.def_path_str(trait_def_id);
 
@@ -1707,9 +1882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
         // references the trait. Relevant for the first case in
         // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
-        let reported =
-            self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name);
-        Ty::new_error(tcx, reported)
+        self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
     }
 
     pub fn prohibit_generic_args<'a>(
@@ -2013,7 +2186,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     path.segments[..path.segments.len() - 2].iter(),
                     GenericsArgsErrExtend::None,
                 );
-                self.lower_qpath(
+                self.lower_qpath_ty(
                     span,
                     opt_self_ty,
                     def_id,
@@ -2167,11 +2340,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
                 self.lower_const_path_resolved(opt_self_ty, path, hir_id)
             }
-            hir::ConstArgKind::Path(qpath) => ty::Const::new_error_with_message(
-                tcx,
-                qpath.span(),
-                format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
-            ),
+            hir::ConstArgKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
+                debug!(?qself, ?segment);
+                let ty = self.lower_ty(qself);
+                self.lower_assoc_path_const(hir_id, const_arg.span(), ty, qself, segment)
+                    .unwrap_or_else(|guar| Const::new_error(tcx, guar))
+            }
+            hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
+                ty::Const::new_error_with_message(
+                    tcx,
+                    qpath.span(),
+                    format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
+                )
+            }
             hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon),
             hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
         }
@@ -2207,6 +2388,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 );
                 ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
             }
+            Res::Def(DefKind::AssocConst, did) => {
+                debug_assert!(path.segments.len() >= 2);
+                let _ = self.prohibit_generic_args(
+                    path.segments[..path.segments.len() - 2].iter(),
+                    GenericsArgsErrExtend::None,
+                );
+                self.lower_qpath_const(
+                    span,
+                    opt_self_ty,
+                    did,
+                    &path.segments[path.segments.len() - 2],
+                    path.segments.last().unwrap(),
+                )
+            }
             Res::Def(DefKind::Static { .. }, _) => {
                 span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
             }
@@ -2223,7 +2418,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             // Exhaustive match to be clear about what exactly we're considering to be
             // an invalid Res for a const path.
-            Res::Def(
+            res @ (Res::Def(
                 DefKind::Mod
                 | DefKind::Enum
                 | DefKind::Variant
@@ -2237,7 +2432,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 | DefKind::Union
                 | DefKind::Trait
                 | DefKind::ForeignTy
-                | DefKind::AssocConst
                 | DefKind::TyParam
                 | DefKind::Macro(_)
                 | DefKind::LifetimeParam
@@ -2260,12 +2454,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             | Res::Local(_)
             | Res::ToolMod
             | Res::NonMacroAttr(_)
-            | Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
+            | Res::Err) => Const::new_error_with_message(
+                tcx,
+                span,
+                format!("invalid Res {res:?} for const path"),
+            ),
         }
     }
 
-    /// Literals and const generic parameters are eagerly converted to a constant, everything else
-    /// becomes `Unevaluated`.
+    /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
     #[instrument(skip(self), level = "debug")]
     fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> {
         let tcx = self.tcx();
@@ -2464,7 +2661,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
                 debug!(?qself, ?segment);
                 let ty = self.lower_ty(qself);
-                self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false)
+                self.lower_assoc_path_ty(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false)
                     .map(|(ty, _, _)| ty)
                     .unwrap_or_else(|guar| Ty::new_error(tcx, guar))
             }
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index cf18bab950a..50b0e32b95e 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -212,7 +212,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     tcx.par_hir_body_owners(|item_def_id| {
         let def_kind = tcx.def_kind(item_def_id);
         match def_kind {
-            DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id),
+            DefKind::Static { .. } => {
+                tcx.ensure_ok().eval_static_initializer(item_def_id);
+                check::maybe_check_static_with_link_section(tcx, item_def_id);
+            }
             DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
                 let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
                 let cid = GlobalId { instance, promoted: None };
@@ -223,12 +226,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         }
     });
 
-    // FIXME: Remove this when we implement creating `DefId`s
-    // for anon constants during their parents' typeck.
-    // Typeck all body owners in parallel will produce queries
-    // cycle errors because it may typeck on anon constants directly.
     tcx.par_hir_body_owners(|item_def_id| {
         let def_kind = tcx.def_kind(item_def_id);
+        // Skip `AnonConst`s because we feed their `type_of`.
         if !matches!(def_kind, DefKind::AnonConst) {
             tcx.ensure_ok().typeck(item_def_id);
         }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index e06398cf3c4..1658c8dac67 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -117,6 +117,80 @@ impl<'a> State<'a> {
                 ));
                 self.hardbreak()
             }
+            hir::Attribute::Parsed(AttributeKind::Deprecation { deprecation, .. }) => {
+                self.word("#[deprecated");
+
+                // There are three possible forms here:
+                // 1. a form with explicit components like
+                //    `#[deprecated(since = "1.2.3", note = "some note", suggestion = "something")]`
+                //    where each component may be present or absent.
+                // 2. `#[deprecated = "message"]`
+                // 3. `#[deprecated]`
+                //
+                // Let's figure out which we need.
+                // If there's a `since` or `suggestion` value, we're definitely in form 1.
+                if matches!(
+                    deprecation.since,
+                    rustc_attr_parsing::DeprecatedSince::RustcVersion(..)
+                        | rustc_attr_parsing::DeprecatedSince::Future
+                        | rustc_attr_parsing::DeprecatedSince::NonStandard(..)
+                ) || deprecation.suggestion.is_some()
+                {
+                    self.word("(");
+                    let mut use_comma = false;
+
+                    match &deprecation.since {
+                        rustc_attr_parsing::DeprecatedSince::RustcVersion(rustc_version) => {
+                            self.word("since = \"");
+                            self.word(format!(
+                                "{}.{}.{}",
+                                rustc_version.major, rustc_version.minor, rustc_version.patch
+                            ));
+                            self.word("\"");
+                            use_comma = true;
+                        }
+                        rustc_attr_parsing::DeprecatedSince::Future => {
+                            self.word("since = \"future\"");
+                            use_comma = true;
+                        }
+                        rustc_attr_parsing::DeprecatedSince::NonStandard(symbol) => {
+                            self.word("since = \"");
+                            self.word(symbol.to_ident_string());
+                            self.word("\"");
+                            use_comma = true;
+                        }
+                        _ => {}
+                    }
+
+                    if let Some(note) = &deprecation.note {
+                        if use_comma {
+                            self.word(", ");
+                        }
+                        self.word("note = \"");
+                        self.word(note.to_ident_string());
+                        self.word("\"");
+                        use_comma = true;
+                    }
+
+                    if let Some(suggestion) = &deprecation.suggestion {
+                        if use_comma {
+                            self.word(", ");
+                        }
+                        self.word("suggestion = \"");
+                        self.word(suggestion.to_ident_string());
+                        self.word("\"");
+                    }
+                } else if let Some(note) = &deprecation.note {
+                    // We're in form 2: `#[deprecated = "message"]`.
+                    self.word(" = \"");
+                    self.word(note.to_ident_string());
+                    self.word("\"");
+                } else {
+                    // We're in form 3: `#[deprecated]`. Nothing to do here.
+                }
+
+                self.word("]");
+            }
             hir::Attribute::Parsed(pa) => {
                 self.word("#[attr=\"");
                 pa.print_attribute(self);
@@ -2386,6 +2460,7 @@ impl<'a> State<'a> {
     }
 
     fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) {
+        self.print_attrs_as_outer(self.attrs(predicate.hir_id));
         match *predicate.kind {
             hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
                 bound_generic_params,
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index ed80bc3e7be..872861d6289 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -171,10 +171,13 @@ hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function
     .suggestion = cast the value to `{$cast_ty}`
     .teach_help = certain types, like `{$ty}`, must be casted before passing them to a variadic function, because of arcane ABI rules dictated by the C standard
 
-hir_typeck_ptr_cast_add_auto_to_object = adding {$traits_len ->
-    [1] an auto trait {$traits}
+hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len ->
+    [1] auto trait {$traits}
     *[other] auto traits {$traits}
-} to a trait object in a pointer cast may cause UB later on
+} to dyn bound via pointer cast
+    .note = this could allow UB elsewhere
+    .help = use `transmute` if you're sure this is sound
+    .label = unsupported cast
 
 hir_typeck_remove_semi_for_coerce = you might have meant to return the `match` expression
 hir_typeck_remove_semi_for_coerce_expr = this could be implicitly returned but it is a statement, not a tail expression
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index ea4ec345ad0..70b49fea34f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -940,23 +940,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             .collect::<Vec<_>>();
 
                         if !added.is_empty() {
-                            tcx.emit_node_span_lint(
-                                lint::builtin::PTR_CAST_ADD_AUTO_TO_OBJECT,
-                                self.expr.hir_id,
-                                self.span,
-                                errors::PtrCastAddAutoToObject {
-                                    traits_len: added.len(),
-                                    traits: {
-                                        let mut traits: Vec<_> = added
-                                            .into_iter()
-                                            .map(|trait_did| tcx.def_path_str(trait_did))
-                                            .collect();
-
-                                        traits.sort();
-                                        traits.into()
-                                    },
+                            tcx.dcx().emit_err(errors::PtrCastAddAutoToObject {
+                                span: self.span,
+                                traits_len: added.len(),
+                                traits: {
+                                    let mut traits: Vec<_> = added
+                                        .into_iter()
+                                        .map(|trait_did| tcx.def_path_str(trait_did))
+                                        .collect();
+
+                                    traits.sort();
+                                    traits.into()
                                 },
-                            )
+                            });
                         }
 
                         Ok(CastKind::PtrPtrCast)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index a5108e7a032..67419fdf1c3 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -51,15 +51,13 @@ use rustc_infer::traits::{
     PredicateObligations,
 };
 use rustc_middle::span_bug;
-use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
 };
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
-use rustc_session::parse::feature_err;
-use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span, sym};
+use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
@@ -610,8 +608,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
         )];
 
-        let mut has_unsized_tuple_coercion = false;
-
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
         // inference might unify those two inner type variables later.
@@ -690,31 +686,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     // be silent, as it causes a type mismatch later.
                 }
 
-                Ok(Some(impl_source)) => {
-                    // Some builtin coercions are still unstable so we detect
-                    // these here and emit a feature error if coercion doesn't fail
-                    // due to another reason.
-                    match impl_source {
-                        traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
-                            has_unsized_tuple_coercion = true;
-                        }
-                        _ => {}
-                    }
-                    queue.extend(impl_source.nested_obligations())
-                }
+                Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
             }
         }
 
-        if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion() {
-            feature_err(
-                &self.tcx.sess,
-                sym::unsized_tuple_coercion,
-                self.cause.span,
-                "unsized tuple coercion is not stable enough for use and is subject to change",
-            )
-            .emit();
-        }
-
         Ok(coercion)
     }
 
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 20688a5b949..b73cd26927a 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -373,9 +373,14 @@ pub(crate) struct LossyProvenanceInt2Ptr<'tcx> {
     pub sugg: LossyProvenanceInt2PtrSuggestion,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(hir_typeck_ptr_cast_add_auto_to_object)]
+#[derive(Diagnostic)]
+#[diag(hir_typeck_ptr_cast_add_auto_to_object, code = E0804)]
+#[note]
+#[help]
 pub(crate) struct PtrCastAddAutoToObject {
+    #[primary_span]
+    #[label]
+    pub span: Span,
     pub traits_len: usize,
     pub traits: DiagSymbolList<String>,
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index dec1779d92c..cbe677171a0 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1806,7 +1806,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
 
         let ty = fcx.check_expr_with_expectation(body.value, expected);
-        fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized);
+        fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic);
         fcx.write_ty(block.hir_id, ty);
         ty
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index e60a4bb47b5..82e99ca7afa 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2174,7 +2174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let result = self
                     .lowerer()
-                    .lower_assoc_path(hir_id, path_span, ty.raw, qself, segment, true);
+                    .lower_assoc_path_ty(hir_id, path_span, ty.raw, qself, segment, true);
                 let ty = result
                     .map(|(ty, _, _)| ty)
                     .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 42236ac6d80..e14f1528d2c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -17,7 +17,7 @@ use rustc_infer::infer;
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
-use rustc_span::{self, DUMMY_SP, Ident, Span, sym};
+use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
 use rustc_trait_selection::error_reporting::TypeErrCtxt;
 use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
@@ -308,15 +308,17 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
         ))
     }
 
-    fn lower_assoc_ty(
+    fn lower_assoc_shared(
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'tcx>,
+        item_segment: &rustc_hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Ty<'tcx> {
+        _kind: ty::AssocKind,
+    ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
         let trait_ref = self.instantiate_binder_with_fresh_vars(
             span,
+            // FIXME(mgca): this should be assoc const if that is the `kind`
             infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id),
             poly_trait_ref,
         );
@@ -328,7 +330,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
             trait_ref.args,
         );
 
-        Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
+        Ok((item_def_id, item_args))
     }
 
     fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 553215ca0af..e47385d0899 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -2,14 +2,14 @@ use std::any::Any;
 use std::ffi::OsString;
 use std::io::{self, BufWriter, Write};
 use std::path::{Path, PathBuf};
-use std::sync::{Arc, LazyLock};
+use std::sync::{Arc, LazyLock, OnceLock};
 use std::{env, fs, iter};
 
 use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
+use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal};
 use rustc_expand::base::{ExtCtxt, LintStoreExpand};
 use rustc_feature::Features;
 use rustc_fs_util::try_canonicalize;
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 5c5b3b350dd..7018774e5c6 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -599,6 +599,11 @@ fn register_builtins(store: &mut LintStore) {
         "converted into hard error, \
          see <https://github.com/rust-lang/rust/issues/73333> for more information",
     );
+    store.register_removed(
+        "ptr_cast_add_auto_to_object",
+        "converted into hard error, see issue #127323 \
+         <https://github.com/rust-lang/rust/issues/127323> for more information",
+    );
 }
 
 fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index cb83d405cc3..d2b08eab479 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,7 +1,7 @@
 use std::iter;
 use std::ops::ControlFlow;
 
-use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange};
+use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::intravisit::VisitorExt;
@@ -1349,7 +1349,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             ty::FnPtr(sig_tys, hdr) => {
                 let sig = sig_tys.with(hdr);
-                if self.is_internal_abi(sig.abi()) {
+                if sig.abi().is_rustic_abi() {
                     return FfiUnsafe {
                         ty,
                         reason: fluent::lint_improper_ctypes_fnptr_reason,
@@ -1552,13 +1552,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 
-    fn is_internal_abi(&self, abi: ExternAbi) -> bool {
-        matches!(
-            abi,
-            ExternAbi::Rust | ExternAbi::RustCall | ExternAbi::RustCold | ExternAbi::RustIntrinsic
-        )
-    }
-
     /// Find any fn-ptr types with external ABIs in `ty`.
     ///
     /// For example, `Option<extern "C" fn()>` returns `extern "C" fn()`
@@ -1567,17 +1560,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         hir_ty: &hir::Ty<'tcx>,
         ty: Ty<'tcx>,
     ) -> Vec<(Ty<'tcx>, Span)> {
-        struct FnPtrFinder<'a, 'b, 'tcx> {
-            visitor: &'a ImproperCTypesVisitor<'b, 'tcx>,
+        struct FnPtrFinder<'tcx> {
             spans: Vec<Span>,
             tys: Vec<Ty<'tcx>>,
         }
 
-        impl<'a, 'b, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'a, 'b, 'tcx> {
+        impl<'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'tcx> {
             fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) {
                 debug!(?ty);
                 if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind
-                    && !self.visitor.is_internal_abi(*abi)
+                    && !abi.is_rustic_abi()
                 {
                     self.spans.push(ty.span);
                 }
@@ -1586,12 +1578,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             }
         }
 
-        impl<'a, 'b, 'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'a, 'b, 'tcx> {
+        impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'tcx> {
             type Result = ();
 
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 if let ty::FnPtr(_, hdr) = ty.kind()
-                    && !self.visitor.is_internal_abi(hdr.abi)
+                    && !hdr.abi.is_rustic_abi()
                 {
                     self.tys.push(ty);
                 }
@@ -1600,7 +1592,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             }
         }
 
-        let mut visitor = FnPtrFinder { visitor: self, spans: Vec::new(), tys: Vec::new() };
+        let mut visitor = FnPtrFinder { spans: Vec::new(), tys: Vec::new() };
         ty.visit_with(&mut visitor);
         visitor.visit_ty_unambig(hir_ty);
 
@@ -1615,13 +1607,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
 
         match it.kind {
             hir::ForeignItemKind::Fn(sig, _, _) => {
-                if vis.is_internal_abi(abi) {
+                if abi.is_rustic_abi() {
                     vis.check_fn(it.owner_id.def_id, sig.decl)
                 } else {
                     vis.check_foreign_fn(it.owner_id.def_id, sig.decl);
                 }
             }
-            hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => {
+            hir::ForeignItemKind::Static(ty, _, _) if !abi.is_rustic_abi() => {
                 vis.check_foreign_static(it.owner_id, ty.span);
             }
             hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (),
@@ -1775,7 +1767,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
         };
 
         let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
-        if vis.is_internal_abi(abi) {
+        if abi.is_rustic_abi() {
             vis.check_fn(id, decl);
         } else {
             vis.check_foreign_fn(id, decl);
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 97850a2afc1..10b85be2cfb 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -80,7 +80,6 @@ declare_lint_pass! {
         PRIVATE_BOUNDS,
         PRIVATE_INTERFACES,
         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-        PTR_CAST_ADD_AUTO_TO_OBJECT,
         PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
         PUB_USE_OF_PRIVATE_EXTERN_CRATE,
         REDUNDANT_IMPORTS,
@@ -3782,7 +3781,7 @@ declare_lint! {
     Warn,
     "use of unsupported calling convention for function pointer",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
         reference: "issue #130260 <https://github.com/rust-lang/rust/issues/130260>",
     };
 }
@@ -4828,58 +4827,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `ptr_cast_add_auto_to_object` lint detects casts of raw pointers to trait
-    /// objects, which add auto traits.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,edition2021,compile_fail
-    /// let ptr: *const dyn core::any::Any = &();
-    /// _ = ptr as *const dyn core::any::Any + Send;
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Adding an auto trait can make the vtable invalid, potentially causing
-    /// UB in safe code afterwards. For example:
-    ///
-    /// ```ignore (causes a warning)
-    /// #![feature(arbitrary_self_types)]
-    ///
-    /// trait Trait {
-    ///     fn f(self: *const Self)
-    ///     where
-    ///         Self: Send;
-    /// }
-    ///
-    /// impl Trait for *const () {
-    ///     fn f(self: *const Self) {
-    ///         unreachable!()
-    ///     }
-    /// }
-    ///
-    /// fn main() {
-    ///     let unsend: *const () = &();
-    ///     let unsend: *const dyn Trait = &unsend;
-    ///     let send_bad: *const (dyn Trait + Send) = unsend as _;
-    ///     send_bad.f(); // this crashes, since vtable for `*const ()` does not have an entry for `f`
-    /// }
-    /// ```
-    ///
-    /// Generally you must ensure that vtable is right for the pointer's type,
-    /// before passing the pointer to safe code.
-    pub PTR_CAST_ADD_AUTO_TO_OBJECT,
-    Warn,
-    "detects `as` casts from pointers to `dyn Trait` to pointers to `dyn Trait + Auto`",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
-        reference: "issue #127323 <https://github.com/rust-lang/rust/issues/127323>",
-    };
-}
-
-declare_lint! {
     /// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope,
     /// above their definition, which may happen in key-value attributes.
     ///
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index df0a25712cc..20f66fae5c0 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -244,6 +244,9 @@ metadata_prev_alloc_error_handler =
 metadata_prev_global_alloc =
     previous global allocator defined here
 
+metadata_raw_dylib_elf_unstable =
+    link kind `raw-dylib` is unstable on ELF platforms
+
 metadata_raw_dylib_no_nul =
     link name must not contain NUL characters if link kind is `raw-dylib`
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index e2d043f47c0..b96921a63f3 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -17,7 +17,7 @@ use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::{Symbol, sym};
-use rustc_target::spec::LinkSelfContainedComponents;
+use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
 
 use crate::{errors, fluent_generated};
 
@@ -263,9 +263,26 @@ impl<'tcx> Collector<'tcx> {
                                 NativeLibKind::Framework { as_needed: None }
                             }
                             "raw-dylib" => {
-                                if !sess.target.is_like_windows {
+                                if sess.target.is_like_windows {
+                                    // raw-dylib is stable and working on Windows
+                                } else if sess.target.binary_format == BinaryFormat::Elf
+                                    && features.raw_dylib_elf()
+                                {
+                                    // raw-dylib is unstable on ELF, but the user opted in
+                                } else if sess.target.binary_format == BinaryFormat::Elf
+                                    && sess.is_nightly_build()
+                                {
+                                    feature_err(
+                                        sess,
+                                        sym::raw_dylib_elf,
+                                        span,
+                                        fluent_generated::metadata_raw_dylib_elf_unstable,
+                                    )
+                                    .emit();
+                                } else {
                                     sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
                                 }
+
                                 NativeLibKind::RawDylib
                             }
                             "link-arg" => {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index e8d9d17872f..6ffbebfffd5 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -2,7 +2,7 @@
 
 use std::iter::TrustedLen;
 use std::path::Path;
-use std::sync::Arc;
+use std::sync::{Arc, OnceLock};
 use std::{io, iter, mem};
 
 pub(super) use cstore_impl::provide;
@@ -11,7 +11,7 @@ use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::owned_slice::OwnedSlice;
-use rustc_data_structures::sync::{Lock, OnceLock};
+use rustc_data_structures::sync::Lock;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 171542d1279..d0dbf64dc59 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -1,8 +1,9 @@
+use std::sync::OnceLock;
+
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph;
 use rustc_data_structures::graph::dominators::{Dominators, dominators};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceLock;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 95bc9b71fe0..697a0e6592d 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -222,7 +222,7 @@ impl AllocError {
 }
 
 /// The information that makes up a memory access: offset and size.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone)]
 pub struct AllocRange {
     pub start: Size,
     pub size: Size,
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 2f13f963578..82fb5f33b4c 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -2,6 +2,7 @@
 //! representation for the common case where PTR_SIZE consecutive bytes have the same provenance.
 
 use std::cmp;
+use std::ops::Range;
 
 use rustc_abi::{HasDataLayout, Size};
 use rustc_data_structures::sorted_map::SortedMap;
@@ -66,6 +67,15 @@ impl ProvenanceMap {
 }
 
 impl<Prov: Provenance> ProvenanceMap<Prov> {
+    fn adjusted_range(range: AllocRange, cx: &impl HasDataLayout) -> Range<Size> {
+        // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
+        // the beginning of this range.
+        let adjusted_start = Size::from_bytes(
+            range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1),
+        );
+        adjusted_start..range.end()
+    }
+
     /// Returns all ptr-sized provenance in the given range.
     /// If the range has length 0, returns provenance that crosses the edge between `start-1` and
     /// `start`.
@@ -74,12 +84,17 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
         range: AllocRange,
         cx: &impl HasDataLayout,
     ) -> &[(Size, Prov)] {
-        // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
-        // the beginning of this range.
-        let adjusted_start = Size::from_bytes(
-            range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1),
-        );
-        self.ptrs.range(adjusted_start..range.end())
+        self.ptrs.range(Self::adjusted_range(range, cx))
+    }
+
+    /// `pm.range_get_ptrs_is_empty(r, cx)` == `pm.range_get_ptrs(r, cx).is_empty()`, but is
+    /// faster.
+    pub(super) fn range_get_ptrs_is_empty(
+        &self,
+        range: AllocRange,
+        cx: &impl HasDataLayout,
+    ) -> bool {
+        self.ptrs.range_is_empty(Self::adjusted_range(range, cx))
     }
 
     /// Returns all byte-wise provenance in the given range.
@@ -117,7 +132,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
     /// limit access to provenance outside of the `Allocation` abstraction.
     ///
     pub fn range_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool {
-        self.range_get_ptrs(range, cx).is_empty() && self.range_get_bytes(range).is_empty()
+        self.range_get_ptrs_is_empty(range, cx) && self.range_get_bytes(range).is_empty()
     }
 
     /// Yields all the provenances stored in this map.
@@ -149,12 +164,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
         // provenance that overlaps with the given range.
         let (first, last) = {
             // Find all provenance overlapping the given range.
-            let provenance = self.range_get_ptrs(range, cx);
-            if provenance.is_empty() {
-                // No provenance in this range, we are done.
+            if self.range_get_ptrs_is_empty(range, cx) {
+                // No provenance in this range, we are done. This is the common case.
                 return Ok(());
             }
 
+            // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much
+            // colder than the early return above, so it's worth it.
+            let provenance = self.range_get_ptrs(range, cx);
             (
                 provenance.first().unwrap().0,
                 provenance.last().unwrap().0 + cx.data_layout().pointer_size,
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 1489d57aba6..98314b5abfd 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -508,6 +508,14 @@ impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
     }
 }
 
+impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) {
+    type Cache<V> = DefaultCache<Self, V>;
+
+    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl Key for (Symbol, u32, u32) {
     type Cache<V> = DefaultCache<Self, V>;
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1302027aabb..4ad4427594c 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2262,22 +2262,13 @@ rustc_queries! {
         desc { "normalizing `{}`", goal.value }
     }
 
-    query implied_outlives_bounds_compat(
-        goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
-    ) -> Result<
-        &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
-        NoSolution,
-    > {
-        desc { "computing implied outlives bounds for `{}`", goal.canonical.value.value.ty }
-    }
-
     query implied_outlives_bounds(
-        goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
+        key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool)
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
         NoSolution,
     > {
-        desc { "computing implied outlives bounds v2 for `{}`", goal.canonical.value.value.ty }
+        desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 }
     }
 
     /// Do not call this query directly:
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index d033ecc75db..b8698aa8233 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -266,7 +266,7 @@ pub enum ObligationCauseCode<'tcx> {
     },
 
     /// Constant expressions must be sized.
-    ConstSized,
+    SizedConstOrStatic,
 
     /// `static` items must have `Sync` type.
     SharedStatic,
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 6309dd2e490..ce4c08aa485 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -3,7 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_macros::{Decodable, Encodable, HashStable};
-use rustc_span::{Ident, Symbol};
+use rustc_span::{Ident, Symbol, sym};
 
 use super::{TyCtxt, Visibility};
 use crate::ty;
@@ -108,6 +108,24 @@ impl AssocItem {
     pub fn is_impl_trait_in_trait(&self) -> bool {
         self.opt_rpitit_info.is_some()
     }
+
+    /// Returns true if:
+    /// - This trait associated item has the `#[type_const]` attribute,
+    /// - If it is in a trait impl, the item from the original trait has this attribute, or
+    /// - It is an inherent assoc const.
+    pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool {
+        if self.kind != ty::AssocKind::Const {
+            return false;
+        }
+
+        let def_id = match (self.container, self.trait_item_def_id) {
+            (AssocItemContainer::Trait, _) => self.def_id,
+            (AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did,
+            // Inherent impl but this attr is only applied to trait assoc items.
+            (AssocItemContainer::Impl, None) => return true,
+        };
+        tcx.has_attr(def_id, sym::type_const)
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index c77b37a302b..34d85534d0a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -133,6 +133,20 @@ pub macro with_no_queries($e:expr) {{
     ))
 }}
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum WrapBinderMode {
+    ForAll,
+    Unsafe,
+}
+impl WrapBinderMode {
+    pub fn start_str(self) -> &'static str {
+        match self {
+            WrapBinderMode::ForAll => "for<",
+            WrapBinderMode::Unsafe => "unsafe<",
+        }
+    }
+}
+
 /// The "region highlights" are used to control region printing during
 /// specific error messages. When a "region highlight" is enabled, it
 /// gives an alternate way to print specific regions. For now, we
@@ -219,7 +233,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         self.print_def_path(def_id, args)
     }
 
-    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
+    fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -229,6 +243,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     fn wrap_binder<T, F: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
+        _mode: WrapBinderMode,
         f: F,
     ) -> Result<(), PrintError>
     where
@@ -703,8 +718,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))),
             ty::UnsafeBinder(ref bound_ty) => {
-                // FIXME(unsafe_binders): Make this print `unsafe<>` rather than `for<>`.
-                self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?;
+                self.wrap_binder(bound_ty, WrapBinderMode::Unsafe, |ty, cx| {
+                    cx.pretty_print_type(*ty)
+                })?;
             }
             ty::Infer(infer_ty) => {
                 if self.should_print_verbose() {
@@ -1067,29 +1083,33 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             };
 
             if let Some(return_ty) = entry.return_ty {
-                self.wrap_binder(&bound_args_and_self_ty, |(args, _), cx| {
-                    define_scoped_cx!(cx);
-                    p!(write("{}", tcx.item_name(trait_def_id)));
-                    p!("(");
-
-                    for (idx, ty) in args.iter().enumerate() {
-                        if idx > 0 {
-                            p!(", ");
+                self.wrap_binder(
+                    &bound_args_and_self_ty,
+                    WrapBinderMode::ForAll,
+                    |(args, _), cx| {
+                        define_scoped_cx!(cx);
+                        p!(write("{}", tcx.item_name(trait_def_id)));
+                        p!("(");
+
+                        for (idx, ty) in args.iter().enumerate() {
+                            if idx > 0 {
+                                p!(", ");
+                            }
+                            p!(print(ty));
                         }
-                        p!(print(ty));
-                    }
 
-                    p!(")");
-                    if let Some(ty) = return_ty.skip_binder().as_type() {
-                        if !ty.is_unit() {
-                            p!(" -> ", print(return_ty));
+                        p!(")");
+                        if let Some(ty) = return_ty.skip_binder().as_type() {
+                            if !ty.is_unit() {
+                                p!(" -> ", print(return_ty));
+                            }
                         }
-                    }
-                    p!(write("{}", if paren_needed { ")" } else { "" }));
+                        p!(write("{}", if paren_needed { ")" } else { "" }));
 
-                    first = false;
-                    Ok(())
-                })?;
+                        first = false;
+                        Ok(())
+                    },
+                )?;
             } else {
                 // Otherwise, render this like a regular trait.
                 traits.insert(
@@ -1110,7 +1130,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         for (trait_pred, assoc_items) in traits {
             write!(self, "{}", if first { "" } else { " + " })?;
 
-            self.wrap_binder(&trait_pred, |trait_pred, cx| {
+            self.wrap_binder(&trait_pred, WrapBinderMode::ForAll, |trait_pred, cx| {
                 define_scoped_cx!(cx);
 
                 if trait_pred.polarity == ty::PredicatePolarity::Negative {
@@ -1302,7 +1322,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         let mut first = true;
 
         if let Some(bound_principal) = predicates.principal() {
-            self.wrap_binder(&bound_principal, |principal, cx| {
+            self.wrap_binder(&bound_principal, WrapBinderMode::ForAll, |principal, cx| {
                 define_scoped_cx!(cx);
                 p!(print_def_path(principal.def_id, &[]));
 
@@ -1927,7 +1947,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
 
         write!(self, "impl ")?;
-        self.wrap_binder(&sig, |sig, cx| {
+        self.wrap_binder(&sig, WrapBinderMode::ForAll, |sig, cx| {
             define_scoped_cx!(cx);
 
             p!(write("{kind}("));
@@ -2367,22 +2387,23 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         Ok(())
     }
 
-    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
+    fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
-        self.pretty_in_binder(value)
+        self.pretty_print_in_binder(value)
     }
 
     fn wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), PrintError>>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
+        mode: WrapBinderMode,
         f: C,
     ) -> Result<(), PrintError>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        self.pretty_wrap_binder(value, f)
+        self.pretty_wrap_binder(value, mode, f)
     }
 
     fn typed_value(
@@ -2632,6 +2653,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
     pub fn name_all_regions<T>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
+        mode: WrapBinderMode,
     ) -> Result<(T, UnordMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
@@ -2705,9 +2727,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         // anyways.
         let (new_value, map) = if self.should_print_verbose() {
             for var in value.bound_vars().iter() {
-                start_or_continue(self, "for<", ", ");
+                start_or_continue(self, mode.start_str(), ", ");
                 write!(self, "{var:?}")?;
             }
+            // Unconditionally render `unsafe<>`.
+            if value.bound_vars().is_empty() && mode == WrapBinderMode::Unsafe {
+                start_or_continue(self, mode.start_str(), "");
+            }
             start_or_continue(self, "", "> ");
             (value.clone().skip_binder(), UnordMap::default())
         } else {
@@ -2772,8 +2798,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     }
                 };
 
-                if !trim_path {
-                    start_or_continue(self, "for<", ", ");
+                // Unconditionally render `unsafe<>`.
+                if !trim_path || mode == WrapBinderMode::Unsafe {
+                    start_or_continue(self, mode.start_str(), ", ");
                     do_continue(self, name);
                 }
                 ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
@@ -2786,9 +2813,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             };
             let new_value = value.clone().skip_binder().fold_with(&mut folder);
             let region_map = folder.region_map;
-            if !trim_path {
-                start_or_continue(self, "", "> ");
+
+            if mode == WrapBinderMode::Unsafe && region_map.is_empty() {
+                start_or_continue(self, mode.start_str(), "");
             }
+            start_or_continue(self, "", "> ");
+
             (new_value, region_map)
         };
 
@@ -2797,12 +2827,15 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         Ok((new_value, map))
     }
 
-    pub fn pretty_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), fmt::Error>
+    pub fn pretty_print_in_binder<T>(
+        &mut self,
+        value: &ty::Binder<'tcx, T>,
+    ) -> Result<(), fmt::Error>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
-        let (new_value, _) = self.name_all_regions(value)?;
+        let (new_value, _) = self.name_all_regions(value, WrapBinderMode::ForAll)?;
         new_value.print(self)?;
         self.region_index = old_region_index;
         self.binder_depth -= 1;
@@ -2812,13 +2845,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
     pub fn pretty_wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
+        mode: WrapBinderMode,
         f: C,
     ) -> Result<(), fmt::Error>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
-        let (new_value, _) = self.name_all_regions(value)?;
+        let (new_value, _) = self.name_all_regions(value, mode)?;
         f(&new_value, self)?;
         self.region_index = old_region_index;
         self.binder_depth -= 1;
@@ -2877,7 +2911,7 @@ where
     T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>,
 {
     fn print(&self, cx: &mut P) -> Result<(), PrintError> {
-        cx.in_binder(self)
+        cx.print_in_binder(self)
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 10b43390eb2..c6f3e22e95f 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -6,27 +6,25 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 use crate::builder::Builder;
 use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
-use crate::builder::matches::{FlatPat, MatchPairTree, TestCase};
+use crate::builder::matches::{FlatPat, MatchPairTree, PatternExtraData, TestCase};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    /// Builds and returns [`MatchPairTree`] subtrees, one for each pattern in
+    /// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in
     /// `subpatterns`, representing the fields of a [`PatKind::Variant`] or
     /// [`PatKind::Leaf`].
     ///
     /// Used internally by [`MatchPairTree::for_pattern`].
     fn field_match_pairs(
         &mut self,
+        match_pairs: &mut Vec<MatchPairTree<'tcx>>,
+        extra_data: &mut PatternExtraData<'tcx>,
         place: PlaceBuilder<'tcx>,
         subpatterns: &[FieldPat<'tcx>],
-    ) -> Vec<MatchPairTree<'tcx>> {
-        subpatterns
-            .iter()
-            .map(|fieldpat| {
-                let place =
-                    place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
-                MatchPairTree::for_pattern(place, &fieldpat.pattern, self)
-            })
-            .collect()
+    ) {
+        for fieldpat in subpatterns {
+            let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
+            MatchPairTree::for_pattern(place, &fieldpat.pattern, self, match_pairs, extra_data);
+        }
     }
 
     /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an
@@ -36,6 +34,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn prefix_slice_suffix(
         &mut self,
         match_pairs: &mut Vec<MatchPairTree<'tcx>>,
+        extra_data: &mut PatternExtraData<'tcx>,
         place: &PlaceBuilder<'tcx>,
         prefix: &[Pat<'tcx>],
         opt_slice: &Option<Box<Pat<'tcx>>>,
@@ -56,11 +55,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ((prefix.len() + suffix.len()).try_into().unwrap(), false)
         };
 
-        match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
+        for (idx, subpattern) in prefix.iter().enumerate() {
             let elem =
                 ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
-            MatchPairTree::for_pattern(place.clone_project(elem), subpattern, self)
-        }));
+            let place = place.clone_project(elem);
+            MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
+        }
 
         if let Some(subslice_pat) = opt_slice {
             let suffix_len = suffix.len() as u64;
@@ -69,10 +69,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 to: if exact_size { min_length - suffix_len } else { suffix_len },
                 from_end: !exact_size,
             });
-            match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self));
+            MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data);
         }
 
-        match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
+        for (idx, subpattern) in suffix.iter().rev().enumerate() {
             let end_offset = (idx + 1) as u64;
             let elem = ProjectionElem::ConstantIndex {
                 offset: if exact_size { min_length - end_offset } else { end_offset },
@@ -80,19 +80,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 from_end: !exact_size,
             };
             let place = place.clone_project(elem);
-            MatchPairTree::for_pattern(place, subpattern, self)
-        }));
+            MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
+        }
     }
 }
 
 impl<'tcx> MatchPairTree<'tcx> {
     /// Recursively builds a match pair tree for the given pattern and its
     /// subpatterns.
-    pub(in crate::builder) fn for_pattern(
+    pub(super) fn for_pattern(
         mut place_builder: PlaceBuilder<'tcx>,
         pattern: &Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
-    ) -> MatchPairTree<'tcx> {
+        match_pairs: &mut Vec<Self>, // Newly-created nodes are added to this vector
+        extra_data: &mut PatternExtraData<'tcx>, // Bindings/ascriptions are added here
+    ) {
         // Force the place type to the pattern's type.
         // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
         if let Some(resolved) = place_builder.resolve_upvar(cx) {
@@ -113,64 +115,102 @@ impl<'tcx> MatchPairTree<'tcx> {
             place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
         }
 
+        // Place can be none if the pattern refers to a non-captured place in a closure.
         let place = place_builder.try_to_place(cx);
-        let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
         let mut subpairs = Vec::new();
         let test_case = match pattern.kind {
-            PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
+            PatKind::Wild | PatKind::Error(_) => None,
 
-            PatKind::Or { ref pats } => TestCase::Or {
+            PatKind::Or { ref pats } => Some(TestCase::Or {
                 pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
-            },
+            }),
 
             PatKind::Range(ref range) => {
                 if range.is_full_range(cx.tcx) == Some(true) {
-                    default_irrefutable()
+                    None
                 } else {
-                    TestCase::Range(Arc::clone(range))
+                    Some(TestCase::Range(Arc::clone(range)))
                 }
             }
 
-            PatKind::Constant { value } => TestCase::Constant { value },
+            PatKind::Constant { value } => Some(TestCase::Constant { value }),
 
             PatKind::AscribeUserType {
                 ascription: Ascription { ref annotation, variance },
                 ref subpattern,
                 ..
             } => {
+                MatchPairTree::for_pattern(
+                    place_builder,
+                    subpattern,
+                    cx,
+                    &mut subpairs,
+                    extra_data,
+                );
+
                 // Apply the type ascription to the value at `match_pair.place`
-                let ascription = place.map(|source| super::Ascription {
-                    annotation: annotation.clone(),
-                    source,
-                    variance,
-                });
-
-                subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx));
-                TestCase::Irrefutable { ascription, binding: None }
+                if let Some(source) = place {
+                    let annotation = annotation.clone();
+                    extra_data.ascriptions.push(super::Ascription { source, annotation, variance });
+                }
+
+                None
             }
 
             PatKind::Binding { mode, var, ref subpattern, .. } => {
-                let binding = place.map(|source| super::Binding {
-                    span: pattern.span,
-                    source,
-                    var_id: var,
-                    binding_mode: mode,
-                });
+                // In order to please the borrow checker, when lowering a pattern
+                // like `x @ subpat` we must establish any bindings in `subpat`
+                // before establishing the binding for `x`.
+                //
+                // For example (from #69971):
+                //
+                // ```ignore (illustrative)
+                // struct NonCopyStruct {
+                //     copy_field: u32,
+                // }
+                //
+                // fn foo1(x: NonCopyStruct) {
+                //     let y @ NonCopyStruct { copy_field: z } = x;
+                //     // the above should turn into
+                //     let z = x.copy_field;
+                //     let y = x;
+                // }
+                // ```
 
+                // First, recurse into the subpattern, if any.
                 if let Some(subpattern) = subpattern.as_ref() {
                     // this is the `x @ P` case; have to keep matching against `P` now
-                    subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx));
+                    MatchPairTree::for_pattern(
+                        place_builder,
+                        subpattern,
+                        cx,
+                        &mut subpairs,
+                        extra_data,
+                    );
                 }
-                TestCase::Irrefutable { ascription: None, binding }
+
+                // Then push this binding, after any bindings in the subpattern.
+                if let Some(source) = place {
+                    extra_data.bindings.push(super::Binding {
+                        span: pattern.span,
+                        source,
+                        var_id: var,
+                        binding_mode: mode,
+                    });
+                }
+
+                None
             }
 
             PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
-                subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
-                default_irrefutable()
+                MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
+                None
             }
             PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
+                MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
+
                 // Apply a type ascription for the inline constant to the value at `match_pair.place`
-                let ascription = place.map(|source| {
+                if let Some(source) = place {
                     let span = pattern.span;
                     let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
                     let args = ty::InlineConstArgs::new(
@@ -189,33 +229,47 @@ impl<'tcx> MatchPairTree<'tcx> {
                         span,
                         user_ty: Box::new(user_ty),
                     };
-                    super::Ascription { annotation, source, variance: ty::Contravariant }
-                });
+                    let variance = ty::Contravariant;
+                    extra_data.ascriptions.push(super::Ascription { annotation, source, variance });
+                }
 
-                subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
-                TestCase::Irrefutable { ascription, binding: None }
+                None
             }
 
             PatKind::Array { ref prefix, ref slice, ref suffix } => {
-                cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
-                default_irrefutable()
+                cx.prefix_slice_suffix(
+                    &mut subpairs,
+                    extra_data,
+                    &place_builder,
+                    prefix,
+                    slice,
+                    suffix,
+                );
+                None
             }
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
-                cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
+                cx.prefix_slice_suffix(
+                    &mut subpairs,
+                    extra_data,
+                    &place_builder,
+                    prefix,
+                    slice,
+                    suffix,
+                );
 
                 if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
-                    default_irrefutable()
+                    None
                 } else {
-                    TestCase::Slice {
+                    Some(TestCase::Slice {
                         len: prefix.len() + suffix.len(),
                         variable_length: slice.is_some(),
-                    }
+                    })
                 }
             }
 
             PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => {
                 let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
-                subpairs = cx.field_match_pairs(downcast_place, subpatterns);
+                cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns);
 
                 let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
                     i == variant_index
@@ -225,21 +279,23 @@ impl<'tcx> MatchPairTree<'tcx> {
                             .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env))
                 }) && (adt_def.did().is_local()
                     || !adt_def.is_variant_list_non_exhaustive());
-                if irrefutable {
-                    default_irrefutable()
-                } else {
-                    TestCase::Variant { adt_def, variant_index }
-                }
+                if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) }
             }
 
             PatKind::Leaf { ref subpatterns } => {
-                subpairs = cx.field_match_pairs(place_builder, subpatterns);
-                default_irrefutable()
+                cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns);
+                None
             }
 
             PatKind::Deref { ref subpattern } => {
-                subpairs.push(MatchPairTree::for_pattern(place_builder.deref(), subpattern, cx));
-                default_irrefutable()
+                MatchPairTree::for_pattern(
+                    place_builder.deref(),
+                    subpattern,
+                    cx,
+                    &mut subpairs,
+                    extra_data,
+                );
+                None
             }
 
             PatKind::DerefPattern { ref subpattern, mutability } => {
@@ -249,23 +305,32 @@ impl<'tcx> MatchPairTree<'tcx> {
                     Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, subpattern.ty, mutability),
                     pattern.span,
                 );
-                subpairs.push(MatchPairTree::for_pattern(
+                MatchPairTree::for_pattern(
                     PlaceBuilder::from(temp).deref(),
                     subpattern,
                     cx,
-                ));
-                TestCase::Deref { temp, mutability }
+                    &mut subpairs,
+                    extra_data,
+                );
+                Some(TestCase::Deref { temp, mutability })
             }
 
-            PatKind::Never => TestCase::Never,
+            PatKind::Never => Some(TestCase::Never),
         };
 
-        MatchPairTree {
-            place,
-            test_case,
-            subpairs,
-            pattern_ty: pattern.ty,
-            pattern_span: pattern.span,
+        if let Some(test_case) = test_case {
+            // This pattern is refutable, so push a new match-pair node.
+            match_pairs.push(MatchPairTree {
+                place: place.expect("refutable patterns should always have a place to inspect"),
+                test_case,
+                subpairs,
+                pattern_ty: pattern.ty,
+                pattern_span: pattern.span,
+            })
+        } else {
+            // This pattern is irrefutable, so it doesn't need its own match-pair node.
+            // Just push its refutable subpatterns instead, if any.
+            match_pairs.extend(subpairs);
         }
     }
 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index d05d5b151ff..b05052a3455 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -26,7 +26,6 @@ use crate::builder::{
 
 // helper functions, broken out by category:
 mod match_pair;
-mod simplify;
 mod test;
 mod util;
 
@@ -987,18 +986,16 @@ impl<'tcx> PatternExtraData<'tcx> {
 }
 
 /// A pattern in a form suitable for lowering the match tree, with all irrefutable
-/// patterns simplified away, and or-patterns sorted to the end.
+/// patterns simplified away.
 ///
-/// Here, "flat" indicates that the pattern's match pairs have been recursively
-/// simplified by [`Builder::simplify_match_pairs`]. They are not necessarily
-/// flat in an absolute sense.
+/// Here, "flat" indicates that irrefutable nodes in the pattern tree have been
+/// recursively replaced with their refutable subpatterns. They are not
+/// necessarily flat in an absolute sense.
 ///
 /// Will typically be incorporated into a [`Candidate`].
 #[derive(Debug, Clone)]
 struct FlatPat<'tcx> {
     /// To match the pattern, all of these must be satisfied...
-    // Invariant: all the match pairs are recursively simplified.
-    // Invariant: or-patterns must be sorted to the end.
     match_pairs: Vec<MatchPairTree<'tcx>>,
 
     extra_data: PatternExtraData<'tcx>,
@@ -1008,17 +1005,15 @@ impl<'tcx> FlatPat<'tcx> {
     /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
     /// for the given pattern.
     fn new(place: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>) -> Self {
-        // First, recursively build a tree of match pairs for the given pattern.
-        let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
+        // Recursively build a tree of match pairs for the given pattern.
+        let mut match_pairs = vec![];
         let mut extra_data = PatternExtraData {
             span: pattern.span,
             bindings: Vec::new(),
             ascriptions: Vec::new(),
             is_never: pattern.is_never_pattern(),
         };
-        // Recursively remove irrefutable match pairs, while recording their
-        // bindings/ascriptions, and sort or-patterns after other match pairs.
-        cx.simplify_match_pairs(&mut match_pairs, &mut extra_data);
+        MatchPairTree::for_pattern(place, pattern, cx, &mut match_pairs, &mut extra_data);
 
         Self { match_pairs, extra_data }
     }
@@ -1055,7 +1050,6 @@ struct Candidate<'tcx> {
     ///   (see [`Builder::test_remaining_match_pairs_after_or`]).
     ///
     /// Invariants:
-    /// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
     /// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
     match_pairs: Vec<MatchPairTree<'tcx>>,
 
@@ -1126,7 +1120,7 @@ impl<'tcx> Candidate<'tcx> {
 
     /// Incorporates an already-simplified [`FlatPat`] into a new candidate.
     fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
-        Candidate {
+        let mut this = Candidate {
             match_pairs: flat_pat.match_pairs,
             extra_data: flat_pat.extra_data,
             has_guard,
@@ -1135,7 +1129,14 @@ impl<'tcx> Candidate<'tcx> {
             otherwise_block: None,
             pre_binding_block: None,
             false_edge_start_block: None,
-        }
+        };
+        this.sort_match_pairs();
+        this
+    }
+
+    /// Restores the invariant that or-patterns must be sorted to the end.
+    fn sort_match_pairs(&mut self) {
+        self.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
     }
 
     /// Returns whether the first match pair of this candidate is an or-pattern.
@@ -1227,17 +1228,11 @@ struct Ascription<'tcx> {
 /// - [`Builder::pick_test_for_match_pair`] (to choose a test)
 /// - [`Builder::sort_candidate`] (to see how the test interacts with a match pair)
 ///
-/// Two variants are unlike the others and deserve special mention:
-///
-/// - [`Self::Irrefutable`] is only used temporarily when building a [`MatchPairTree`].
-///   They are then flattened away by [`Builder::simplify_match_pairs`], with any
-///   bindings/ascriptions incorporated into the enclosing [`FlatPat`].
-/// - [`Self::Or`] are not tested directly like the other variants. Instead they
-///   participate in or-pattern expansion, where they are transformed into subcandidates.
-///   - See [`Builder::expand_and_match_or_candidates`].
+/// Note that or-patterns are not tested directly like the other variants.
+/// Instead they participate in or-pattern expansion, where they are transformed into
+/// subcandidates. See [`Builder::expand_and_match_or_candidates`].
 #[derive(Debug, Clone)]
 enum TestCase<'tcx> {
-    Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
     Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
     Constant { value: mir::Const<'tcx> },
     Range(Arc<PatRange<'tcx>>),
@@ -1261,19 +1256,9 @@ impl<'tcx> TestCase<'tcx> {
 #[derive(Debug, Clone)]
 pub(crate) struct MatchPairTree<'tcx> {
     /// This place...
-    ///
-    /// ---
-    /// This can be `None` if it referred to a non-captured place in a closure.
-    ///
-    /// Invariant: Can only be `None` when `test_case` is `Irrefutable`.
-    /// Therefore this must be `Some(_)` after simplification.
-    place: Option<Place<'tcx>>,
+    place: Place<'tcx>,
 
     /// ... must pass this test...
-    ///
-    /// ---
-    /// Invariant: after creation and simplification in [`FlatPat::new`],
-    /// this must not be [`TestCase::Irrefutable`].
     test_case: TestCase<'tcx>,
 
     /// ... and these subpairs must match.
@@ -2091,11 +2076,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Extract the match-pair from the highest priority candidate
         let match_pair = &candidates[0].match_pairs[0];
         let test = self.pick_test_for_match_pair(match_pair);
-        // Unwrap is ok after simplification.
-        let match_place = match_pair.place.unwrap();
         debug!(?test, ?match_pair);
 
-        (match_place, test)
+        (match_pair.place, test)
     }
 
     /// Given a test, we partition the input candidates into several buckets.
diff --git a/compiler/rustc_mir_build/src/builder/matches/simplify.rs b/compiler/rustc_mir_build/src/builder/matches/simplify.rs
deleted file mode 100644
index 15c860151dc..00000000000
--- a/compiler/rustc_mir_build/src/builder/matches/simplify.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-//! Simplifying Candidates
-//!
-//! *Simplifying* a match pair `place @ pattern` means breaking it down
-//! into bindings or other, simpler match pairs. For example:
-//!
-//! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]`
-//! - `place @ x` can be simplified to `[]` by binding `x` to `place`
-//!
-//! The `simplify_match_pairs` routine just repeatedly applies these
-//! sort of simplifications until there is nothing left to
-//! simplify. Match pairs cannot be simplified if they require some
-//! sort of test: for example, testing which variant an enum is, or
-//! testing a value against a constant.
-
-use std::mem;
-
-use tracing::{debug, instrument};
-
-use crate::builder::Builder;
-use crate::builder::matches::{MatchPairTree, PatternExtraData, TestCase};
-
-impl<'a, 'tcx> Builder<'a, 'tcx> {
-    /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
-    /// ascriptions in `extra_data`.
-    #[instrument(skip(self), level = "debug")]
-    pub(super) fn simplify_match_pairs(
-        &mut self,
-        match_pairs: &mut Vec<MatchPairTree<'tcx>>,
-        extra_data: &mut PatternExtraData<'tcx>,
-    ) {
-        // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
-        // bindings in `pat` before `x`. E.g. (#69971):
-        //
-        // struct NonCopyStruct {
-        //     copy_field: u32,
-        // }
-        //
-        // fn foo1(x: NonCopyStruct) {
-        //     let y @ NonCopyStruct { copy_field: z } = x;
-        //     // the above should turn into
-        //     let z = x.copy_field;
-        //     let y = x;
-        // }
-        //
-        // We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat`
-        // after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
-        // match lowering forces us to lower bindings inside or-patterns last.
-        for mut match_pair in mem::take(match_pairs) {
-            self.simplify_match_pairs(&mut match_pair.subpairs, extra_data);
-            if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
-                if let Some(binding) = binding {
-                    extra_data.bindings.push(binding);
-                }
-                if let Some(ascription) = ascription {
-                    extra_data.ascriptions.push(ascription);
-                }
-                // Simplifiable pattern; we replace it with its already simplified subpairs.
-                match_pairs.append(&mut match_pair.subpairs);
-            } else {
-                // Unsimplifiable pattern; we keep it.
-                match_pairs.push(match_pair);
-            }
-        }
-
-        // Move or-patterns to the end, because they can result in us
-        // creating additional candidates, so we want to test them as
-        // late as possible.
-        match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
-        debug!(simplified = ?match_pairs, "simplify_match_pairs");
-    }
-}
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index a7a028bff97..e5d61bc9e55 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -55,12 +55,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // Or-patterns are not tested directly; instead they are expanded into subcandidates,
             // which are then distinguished by testing whatever non-or patterns they contain.
             TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
-
-            TestCase::Irrefutable { .. } => span_bug!(
-                match_pair.pattern_span,
-                "simplifiable pattern found: {:?}",
-                match_pair.pattern_span
-            ),
         };
 
         Test { span: match_pair.pattern_span, kind }
@@ -546,11 +540,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // than one, but it'd be very unusual to have two sides that
         // both require tests; you'd expect one side to be simplified
         // away.)
-        let (match_pair_index, match_pair) = candidate
-            .match_pairs
-            .iter()
-            .enumerate()
-            .find(|&(_, mp)| mp.place == Some(test_place))?;
+        let (match_pair_index, match_pair) =
+            candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == test_place)?;
 
         // If true, the match pair is completely entailed by its corresponding test
         // branch, so it can be removed. If false, the match pair is _compatible_
@@ -593,7 +584,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     candidate
                         .match_pairs
                         .iter()
-                        .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
+                        .any(|mp| mp.place == test_place && is_covering_range(&mp.test_case))
                 };
                 if sorted_candidates
                     .get(&TestBranch::Failure)
@@ -769,7 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let match_pair = candidate.match_pairs.remove(match_pair_index);
             candidate.match_pairs.extend(match_pair.subpairs);
             // Move or-patterns to the end.
-            candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
+            candidate.sort_match_pairs();
         }
 
         ret
diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs
index 589e350a03f..ed3b652e4ef 100644
--- a/compiler/rustc_mir_build/src/builder/matches/util.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/util.rs
@@ -173,14 +173,10 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
             // }
             // ```
             // Hence we fake borrow using a deep borrow.
-            if let Some(place) = match_pair.place {
-                self.fake_borrow(place, FakeBorrowKind::Deep);
-            }
+            self.fake_borrow(match_pair.place, FakeBorrowKind::Deep);
         } else {
             // Insert a Shallow borrow of any place that is switched on.
-            if let Some(place) = match_pair.place {
-                self.fake_borrow(place, FakeBorrowKind::Shallow);
-            }
+            self.fake_borrow(match_pair.place, FakeBorrowKind::Shallow);
 
             for subpair in &match_pair.subpairs {
                 self.visit_match_pair(subpair);
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 049f13ce96d..a0db8bdb7ed 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -80,35 +80,6 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
         // `f` passes. Note that function arguments are the only situation in which this problem can
         // arise: every other use of `move` in MIR doesn't actually write to the value it moves
         // from.
-        //
-        // Anyway, right now this situation doesn't actually arise in practice. Instead, the MIR for
-        // that function looks like this:
-        //
-        //      fn f(_1: BigStruct) -> () {
-        //          let mut _0: ();
-        //          let mut _2: BigStruct;
-        //          bb0: {
-        //              _2 = move _1;
-        //              _0 = g(move _2) -> bb1;
-        //          }
-        //          ...
-        //      }
-        //
-        // Because of that extra move that MIR construction inserts, `x` (i.e. `_1`) can *in
-        // practice* safely be marked `readonly`.
-        //
-        // To handle the possibility that other optimizations (for example, destination propagation)
-        // might someday generate MIR like the first example above, we panic upon seeing an argument
-        // to *our* function that is directly moved into *another* function as an argument. Having
-        // eliminated that problematic case, we can safely treat moves as copies in this analysis.
-        //
-        // In the future, if MIR optimizations cause arguments of a caller to be directly moved into
-        // the argument of a callee, we can just add that argument to `mutated_args` instead of
-        // panicking.
-        //
-        // Note that, because the problematic MIR is never actually generated, we can't add a test
-        // case for this.
-
         if let TerminatorKind::Call { ref args, .. } = terminator.kind {
             for arg in args {
                 if let Operand::Move(place) = arg.node {
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 7b3553e7afd..abbff1c48dd 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -53,11 +53,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
 
         // Rust calls cannot themselves create foreign unwinds.
         // We assume this is true for intrinsics as well.
-        if let ExternAbi::RustIntrinsic
-        | ExternAbi::Rust
-        | ExternAbi::RustCall
-        | ExternAbi::RustCold = sig.abi()
-        {
+        if sig.abi().is_rustic_abi() {
             continue;
         };
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 5981b5031c6..0183ba19475 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -606,14 +606,14 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
         ty::EarlyBinder::bind(callee_body.clone()),
     ) else {
         debug!("failed to normalize callee body");
-        return Err("implementation limitation");
+        return Err("implementation limitation -- could not normalize callee body");
     };
 
     // Normally, this shouldn't be required, but trait normalization failure can create a
     // validation ICE.
     if !validate_types(tcx, inliner.typing_env(), &callee_body, &caller_body).is_empty() {
         debug!("failed to validate callee body");
-        return Err("implementation limitation");
+        return Err("implementation limitation -- callee body failed validation");
     }
 
     // Check call signature compatibility.
@@ -622,17 +622,9 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
     let output_type = callee_body.return_ty();
     if !util::sub_types(tcx, inliner.typing_env(), output_type, destination_ty) {
         trace!(?output_type, ?destination_ty);
-        debug!("failed to normalize return type");
-        return Err("implementation limitation");
+        return Err("implementation limitation -- return type mismatch");
     }
     if callsite.fn_sig.abi() == ExternAbi::RustCall {
-        // FIXME: Don't inline user-written `extern "rust-call"` functions,
-        // since this is generally perf-negative on rustc, and we hope that
-        // LLVM will inline these functions instead.
-        if callee_body.spread_arg.is_some() {
-            return Err("user-written rust-call functions");
-        }
-
         let (self_arg, arg_tuple) = match &args[..] {
             [arg_tuple] => (None, arg_tuple),
             [self_arg, arg_tuple] => (Some(self_arg), arg_tuple),
@@ -642,12 +634,17 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
         let self_arg_ty = self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, tcx));
 
         let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, tcx);
-        let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
-            bug!("Closure arguments are not passed as a tuple");
+        let arg_tys = if callee_body.spread_arg.is_some() {
+            std::slice::from_ref(&arg_tuple_ty)
+        } else {
+            let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
+                bug!("Closure arguments are not passed as a tuple");
+            };
+            arg_tuple_tys.as_slice()
         };
 
         for (arg_ty, input) in
-            self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
+            self_arg_ty.into_iter().chain(arg_tys.iter().copied()).zip(callee_body.args_iter())
         {
             let input_type = callee_body.local_decls[input].ty;
             if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
@@ -663,7 +660,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
             if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
                 trace!(?arg_ty, ?input_type);
                 debug!("failed to normalize argument type");
-                return Err("implementation limitation");
+                return Err("implementation limitation -- arg mismatch");
             }
         }
     }
@@ -693,13 +690,13 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
             // won't cause cycles on this.
             if !inliner.tcx().is_mir_available(callee_def_id) {
                 debug!("item MIR unavailable");
-                return Err("implementation limitation");
+                return Err("implementation limitation -- MIR unavailable");
             }
         }
         // These have no own callable MIR.
         InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => {
             debug!("instance without MIR (intrinsic / virtual)");
-            return Err("implementation limitation");
+            return Err("implementation limitation -- cannot inline intrinsic");
         }
 
         // FIXME(#127030): `ConstParamHasTy` has bad interactions with
@@ -709,7 +706,7 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
         // substituted.
         InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => {
             debug!("still needs substitution");
-            return Err("implementation limitation");
+            return Err("implementation limitation -- HACK for dropping polymorphic type");
         }
 
         // This cannot result in an immediate cycle since the callee MIR is a shim, which does
@@ -1060,8 +1057,7 @@ fn make_call_args<'tcx, I: Inliner<'tcx>>(
 
         closure_ref_arg.chain(tuple_tmp_args).collect()
     } else {
-        // FIXME(edition_2024): switch back to a normal method call.
-        <_>::into_iter(args)
+        args.into_iter()
             .map(|a| create_temp_if_necessary(inliner, a.node, callsite, caller_body, return_block))
             .collect()
     }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 04c9375b831..5df12ac4d8b 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -513,6 +513,24 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
         body.tainted_by_errors = Some(error_reported);
     }
 
+    // Also taint the body if it's within a top-level item that is not well formed.
+    //
+    // We do this check here and not during `mir_promoted` because that may result
+    // in borrowck cycles if WF requires looking into an opaque hidden type.
+    let root = tcx.typeck_root_def_id(def.to_def_id());
+    match tcx.def_kind(root) {
+        DefKind::Fn
+        | DefKind::AssocFn
+        | DefKind::Static { .. }
+        | DefKind::Const
+        | DefKind::AssocConst => {
+            if let Err(guar) = tcx.check_well_formed(root.expect_local()) {
+                body.tainted_by_errors = Some(guar);
+            }
+        }
+        _ => {}
+    }
+
     run_analysis_to_runtime_passes(tcx, &mut body);
 
     tcx.alloc_steal_mir(body)
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 08df0dedc6b..67fca1d7c29 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -209,7 +209,7 @@ use std::path::PathBuf;
 
 use rustc_attr_parsing::InlineAttr;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::sync::{LRef, MTLock, par_for_each_in};
+use rustc_data_structures::sync::{MTLock, par_for_each_in};
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -357,7 +357,7 @@ impl<'tcx> Extend<Spanned<MonoItem<'tcx>>> for MonoItems<'tcx> {
 fn collect_items_rec<'tcx>(
     tcx: TyCtxt<'tcx>,
     starting_item: Spanned<MonoItem<'tcx>>,
-    state: LRef<'_, SharedState<'tcx>>,
+    state: &SharedState<'tcx>,
     recursion_depths: &mut DefIdMap<usize>,
     recursion_limit: Limit,
     mode: CollectionMode,
@@ -1671,30 +1671,26 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
 
     debug!("building mono item graph, beginning at roots");
 
-    let mut state = SharedState {
+    let state = SharedState {
         visited: MTLock::new(UnordSet::default()),
         mentioned: MTLock::new(UnordSet::default()),
         usage_map: MTLock::new(UsageMap::new()),
     };
     let recursion_limit = tcx.recursion_limit();
 
-    {
-        let state: LRef<'_, _> = &mut state;
-
-        tcx.sess.time("monomorphization_collector_graph_walk", || {
-            par_for_each_in(roots, |root| {
-                let mut recursion_depths = DefIdMap::default();
-                collect_items_rec(
-                    tcx,
-                    dummy_spanned(root),
-                    state,
-                    &mut recursion_depths,
-                    recursion_limit,
-                    CollectionMode::UsedItems,
-                );
-            });
+    tcx.sess.time("monomorphization_collector_graph_walk", || {
+        par_for_each_in(roots, |root| {
+            let mut recursion_depths = DefIdMap::default();
+            collect_items_rec(
+                tcx,
+                dummy_spanned(root),
+                &state,
+                &mut recursion_depths,
+                recursion_limit,
+                CollectionMode::UsedItems,
+            );
         });
-    }
+    });
 
     // The set of MonoItems was created in an inherently indeterministic order because
     // of parallelism. We sort it here to ensure that the output is deterministic.
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 9f26da7d5c6..06d6c3ab805 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,6 +1,6 @@
 //! This module ensures that if a function's ABI requires a particular target feature,
 //! that target feature is enabled both on the callee and all callers.
-use rustc_abi::{BackendRepr, ExternAbi, RegKind};
+use rustc_abi::{BackendRepr, RegKind};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::{self, traversal};
 use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
@@ -115,8 +115,8 @@ fn check_call_site_abi<'tcx>(
     span: Span,
     caller: InstanceKind<'tcx>,
 ) {
-    if callee.fn_sig(tcx).abi() == ExternAbi::Rust {
-        // "Rust" ABI never passes arguments in vector registers.
+    if callee.fn_sig(tcx).abi().is_rustic_abi() {
+        // we directly handle the soundness of Rust ABIs
         return;
     }
     let typing_env = ty::TypingEnv::fully_monomorphized();
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 1b18142c242..12a55664641 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -786,13 +786,6 @@ where
                     )
                 }
 
-                //  `(A, B, T)` -> `(A, B, U)` where `T: Unsize<U>`
-                (ty::Tuple(a_tys), ty::Tuple(b_tys))
-                    if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
-                {
-                    result_to_single(ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys))
-                }
-
                 _ => vec![],
             }
         })
@@ -1084,48 +1077,6 @@ where
             .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
     }
 
-    /// We generate the following builtin impl for tuples of all sizes.
-    ///
-    /// This impl is still unstable and we emit a feature error when it
-    /// when it is used by a coercion.
-    /// ```ignore (builtin impl example)
-    /// impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<(T, V)> for (T, U)
-    /// where
-    ///     U: Unsize<V>,
-    /// {}
-    /// ```
-    fn consider_builtin_tuple_unsize(
-        &mut self,
-        goal: Goal<I, (I::Ty, I::Ty)>,
-        a_tys: I::Tys,
-        b_tys: I::Tys,
-    ) -> Result<Candidate<I>, NoSolution> {
-        let cx = self.cx();
-        let Goal { predicate: (_a_ty, b_ty), .. } = goal;
-
-        let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
-        let b_last_ty = b_tys.last().unwrap();
-
-        // Instantiate just the tail field of B., and require that they're equal.
-        let unsized_a_ty = Ty::new_tup_from_iter(cx, a_rest_tys.iter().copied().chain([b_last_ty]));
-        self.eq(goal.param_env, unsized_a_ty, b_ty)?;
-
-        // Similar to ADTs, require that we can unsize the tail.
-        self.add_goal(
-            GoalSource::ImplWhereBound,
-            goal.with(
-                cx,
-                ty::TraitRef::new(
-                    cx,
-                    cx.require_lang_item(TraitSolverLangItem::Unsize),
-                    [a_last_ty, b_last_ty],
-                ),
-            ),
-        );
-        self.probe_builtin_trait_candidate(BuiltinImplSource::TupleUnsizing)
-            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
-    }
-
     // Return `Some` if there is an impl (built-in or user provided) that may
     // hold for the self type of the goal, which for coherence and soundness
     // purposes must disqualify the built-in auto impl assembled by considering
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 792e2cc26ef..1d17290e1c7 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -384,17 +384,17 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                 rustc_lexer::TokenKind::Colon => token::Colon,
                 rustc_lexer::TokenKind::Dollar => token::Dollar,
                 rustc_lexer::TokenKind::Eq => token::Eq,
-                rustc_lexer::TokenKind::Bang => token::Not,
+                rustc_lexer::TokenKind::Bang => token::Bang,
                 rustc_lexer::TokenKind::Lt => token::Lt,
                 rustc_lexer::TokenKind::Gt => token::Gt,
-                rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus),
-                rustc_lexer::TokenKind::And => token::BinOp(token::And),
-                rustc_lexer::TokenKind::Or => token::BinOp(token::Or),
-                rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus),
-                rustc_lexer::TokenKind::Star => token::BinOp(token::Star),
-                rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash),
-                rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
-                rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
+                rustc_lexer::TokenKind::Minus => token::Minus,
+                rustc_lexer::TokenKind::And => token::And,
+                rustc_lexer::TokenKind::Or => token::Or,
+                rustc_lexer::TokenKind::Plus => token::Plus,
+                rustc_lexer::TokenKind::Star => token::Star,
+                rustc_lexer::TokenKind::Slash => token::Slash,
+                rustc_lexer::TokenKind::Caret => token::Caret,
+                rustc_lexer::TokenKind::Percent => token::Percent,
 
                 rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                     // Don't emit diagnostics for sequences of the same invalid token
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 648a352efd9..ff03b42484b 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -308,11 +308,11 @@ pub(super) static UNICODE_ARRAY: &[(char, &str, &str)] = &[
 const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[
     (" ", "Space", None),
     ("_", "Underscore", Some(token::Ident(kw::Underscore, token::IdentIsRaw::No))),
-    ("-", "Minus/Hyphen", Some(token::BinOp(token::Minus))),
+    ("-", "Minus/Hyphen", Some(token::Minus)),
     (",", "Comma", Some(token::Comma)),
     (";", "Semicolon", Some(token::Semi)),
     (":", "Colon", Some(token::Colon)),
-    ("!", "Exclamation Mark", Some(token::Not)),
+    ("!", "Exclamation Mark", Some(token::Bang)),
     ("?", "Question Mark", Some(token::Question)),
     (".", "Period", Some(token::Dot)),
     ("(", "Left Parenthesis", Some(token::OpenDelim(Delimiter::Parenthesis))),
@@ -321,11 +321,11 @@ const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[
     ("]", "Right Square Bracket", Some(token::CloseDelim(Delimiter::Bracket))),
     ("{", "Left Curly Brace", Some(token::OpenDelim(Delimiter::Brace))),
     ("}", "Right Curly Brace", Some(token::CloseDelim(Delimiter::Brace))),
-    ("*", "Asterisk", Some(token::BinOp(token::Star))),
-    ("/", "Slash", Some(token::BinOp(token::Slash))),
+    ("*", "Asterisk", Some(token::Star)),
+    ("/", "Slash", Some(token::Slash)),
     ("\\", "Backslash", None),
-    ("&", "Ampersand", Some(token::BinOp(token::And))),
-    ("+", "Plus Sign", Some(token::BinOp(token::Plus))),
+    ("&", "Ampersand", Some(token::And)),
+    ("+", "Plus Sign", Some(token::Plus)),
     ("<", "Less-Than Sign", Some(token::Lt)),
     ("=", "Equals Sign", Some(token::Eq)),
     ("==", "Double Equals Sign", Some(token::EqEq)),
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 98fdd35190d..066b570c23f 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -130,7 +130,7 @@ impl<'a> Parser<'a> {
             assert!(this.eat(exp!(Pound)), "parse_attribute called in non-attribute position");
 
             let style =
-                if this.eat(exp!(Not)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
+                if this.eat(exp!(Bang)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
 
             this.expect(exp!(OpenBracket))?;
             let item = this.parse_attr_item(ForceCollect::No)?;
@@ -312,7 +312,7 @@ impl<'a> Parser<'a> {
         loop {
             let start_pos = self.num_bump_calls;
             // Only try to parse if it is an inner attribute (has `!`).
-            let attr = if self.check(exp!(Pound)) && self.look_ahead(1, |t| t == &token::Not) {
+            let attr = if self.check(exp!(Pound)) && self.look_ahead(1, |t| t == &token::Bang) {
                 Some(self.parse_attribute(InnerAttrPolicy::Permitted)?)
             } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                 if attr_style == ast::AttrStyle::Inner {
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 02bcb1fbf70..94db43bb59f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1167,7 +1167,7 @@ impl<'a> Parser<'a> {
         let mut number_of_gt = 0;
         while self.look_ahead(position, |t| {
             trace!("check_trailing_angle_brackets: t={:?}", t);
-            if *t == token::BinOp(token::BinOpToken::Shr) {
+            if *t == token::Shr {
                 number_of_shr += 1;
                 true
             } else if *t == token::Gt {
@@ -1222,7 +1222,7 @@ impl<'a> Parser<'a> {
                     let span = lo.to(self.prev_token.span);
                     // Detect trailing `>` like in `x.collect::Vec<_>>()`.
                     let mut trailing_span = self.prev_token.span.shrink_to_hi();
-                    while self.token == token::BinOp(token::Shr) || self.token == token::Gt {
+                    while self.token == token::Shr || self.token == token::Gt {
                         trailing_span = trailing_span.to(self.token.span);
                         self.bump();
                     }
@@ -1468,8 +1468,7 @@ impl<'a> Parser<'a> {
                         let snapshot = self.create_snapshot_for_diagnostic();
                         self.bump();
                         // So far we have parsed `foo<bar<`, consume the rest of the type args.
-                        let modifiers =
-                            [(token::Lt, 1), (token::Gt, -1), (token::BinOp(token::Shr), -2)];
+                        let modifiers = [(token::Lt, 1), (token::Gt, -1), (token::Shr, -2)];
                         self.consume_tts(1, &modifiers);
 
                         if !&[token::OpenDelim(Delimiter::Parenthesis), token::PathSep]
@@ -1962,7 +1961,7 @@ impl<'a> Parser<'a> {
         &mut self,
         await_sp: Span,
     ) -> PResult<'a, P<Expr>> {
-        let (hi, expr, is_question) = if self.token == token::Not {
+        let (hi, expr, is_question) = if self.token == token::Bang {
             // Handle `await!(<expr>)`.
             self.recover_await_macro()?
         } else {
@@ -1974,7 +1973,7 @@ impl<'a> Parser<'a> {
     }
 
     fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> {
-        self.expect(exp!(Not))?;
+        self.expect(exp!(Bang))?;
         self.expect(exp!(OpenParen))?;
         let expr = self.parse_expr()?;
         self.expect(exp!(CloseParen))?;
@@ -2034,7 +2033,7 @@ impl<'a> Parser<'a> {
 
     pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
         let is_try = self.token.is_keyword(kw::Try);
-        let is_questionmark = self.look_ahead(1, |t| t == &token::Not); //check for !
+        let is_questionmark = self.look_ahead(1, |t| t == &token::Bang); //check for !
         let is_open = self.look_ahead(2, |t| t == &token::OpenDelim(Delimiter::Parenthesis)); //check for (
 
         if is_try && is_questionmark && is_open {
@@ -2613,8 +2612,7 @@ impl<'a> Parser<'a> {
             || self.token == TokenKind::Dot;
         // This will be true when a trait object type `Foo +` or a path which was a `const fn` with
         // type params has been parsed.
-        let was_op =
-            matches!(self.prev_token.kind, token::BinOp(token::Plus | token::Shr) | token::Gt);
+        let was_op = matches!(self.prev_token.kind, token::Plus | token::Shr | token::Gt);
         if !is_op_or_dot && !was_op {
             // We perform these checks and early return to avoid taking a snapshot unnecessarily.
             return Err(err);
@@ -2992,8 +2990,7 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_vcs_conflict_marker(&mut self) {
         // <<<<<<<
-        let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
-        else {
+        let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else {
             return;
         };
         let mut spans = Vec::with_capacity(3);
@@ -3008,15 +3005,13 @@ impl<'a> Parser<'a> {
             if self.token == TokenKind::Eof {
                 break;
             }
-            if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or))
-            {
+            if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or) {
                 middlediff3 = Some(span);
             }
             if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
                 middle = Some(span);
             }
-            if let Some(span) = self.conflict_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt)
-            {
+            if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) {
                 spans.push(span);
                 end = Some(span);
                 break;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ef29ac2719d..0a08c6faeb4 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -239,8 +239,8 @@ impl<'a> Parser<'a> {
                 self.bump();
             }
 
-            if self.prev_token == token::BinOp(token::Plus)
-                && self.token == token::BinOp(token::Plus)
+            if self.prev_token == token::Plus
+                && self.token == token::Plus
                 && self.prev_token.span.between(self.token.span).is_empty()
             {
                 let op_span = self.prev_token.span.to(self.token.span);
@@ -250,8 +250,8 @@ impl<'a> Parser<'a> {
                 continue;
             }
 
-            if self.prev_token == token::BinOp(token::Minus)
-                && self.token == token::BinOp(token::Minus)
+            if self.prev_token == token::Minus
+                && self.token == token::Minus
                 && self.prev_token.span.between(self.token.span).is_empty()
                 && !self.look_ahead(1, |tok| tok.can_begin_expr())
             {
@@ -505,23 +505,23 @@ impl<'a> Parser<'a> {
         // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
         match this.token.uninterpolate().kind {
             // `!expr`
-            token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
+            token::Bang => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
             // `~expr`
             token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
             // `-expr`
-            token::BinOp(token::Minus) => {
+            token::Minus => {
                 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
             }
             // `*expr`
-            token::BinOp(token::Star) => {
+            token::Star => {
                 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
             }
             // `&expr` and `&&expr`
-            token::BinOp(token::And) | token::AndAnd => {
+            token::And | token::AndAnd => {
                 make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
             }
             // `+lit`
-            token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
+            token::Plus if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
                 let mut err = errors::LeadingPlusNotSupported {
                     span: lo,
                     remove_plus: None,
@@ -541,9 +541,7 @@ impl<'a> Parser<'a> {
                 this.parse_expr_prefix(attrs)
             }
             // Recover from `++x`:
-            token::BinOp(token::Plus)
-                if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
-            {
+            token::Plus if this.look_ahead(1, |t| *t == token::Plus) => {
                 let starts_stmt = this.prev_token == token::Semi
                     || this.prev_token == token::CloseDelim(Delimiter::Brace);
                 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
@@ -567,7 +565,11 @@ impl<'a> Parser<'a> {
     fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
         self.bump();
         let attrs = self.parse_outer_attributes()?;
-        let expr = self.parse_expr_prefix(attrs)?;
+        let expr = if self.token.is_range_separator() {
+            self.parse_expr_prefix_range(attrs)
+        } else {
+            self.parse_expr_prefix(attrs)
+        }?;
         let span = self.interpolated_or_expr_span(&expr);
         Ok((lo.to(span), expr))
     }
@@ -723,14 +725,12 @@ impl<'a> Parser<'a> {
                                     suggestion,
                                 })
                             }
-                            token::BinOp(token::Shl) => {
-                                self.dcx().emit_err(errors::ShiftInterpretedAsGeneric {
-                                    shift: self.token.span,
-                                    r#type: path,
-                                    args: args_span,
-                                    suggestion,
-                                })
-                            }
+                            token::Shl => self.dcx().emit_err(errors::ShiftInterpretedAsGeneric {
+                                shift: self.token.span,
+                                r#type: path,
+                                args: args_span,
+                                suggestion,
+                            }),
                             _ => {
                                 // We can end up here even without `<` being the next token, for
                                 // example because `parse_ty_no_plus` returns `Err` on keywords,
@@ -1574,7 +1574,7 @@ impl<'a> Parser<'a> {
         };
 
         // `!`, as an operator, is prefix, so we know this isn't that.
-        let (span, kind) = if self.eat(exp!(Not)) {
+        let (span, kind) = if self.eat(exp!(Bang)) {
             // MACRO INVOCATION expression
             if qself.is_some() {
                 self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
@@ -2595,7 +2595,7 @@ impl<'a> Parser<'a> {
                 missing_let: None,
                 comparison: None,
             };
-            if self.prev_token == token::BinOp(token::Or) {
+            if self.prev_token == token::Or {
                 // This was part of a closure, the that part of the parser recover.
                 return Err(self.dcx().create_err(err));
             } else {
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 11f0e579de5..c3f71dd8b30 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -367,34 +367,47 @@ impl<'a> Parser<'a> {
 
         loop {
             let where_sp = where_lo.to(self.prev_token.span);
+            let attrs = self.parse_outer_attributes()?;
             let pred_lo = self.token.span;
-            let kind = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
-                let lifetime = self.expect_lifetime();
-                // Bounds starting with a colon are mandatory, but possibly empty.
-                self.expect(exp!(Colon))?;
-                let bounds = self.parse_lt_param_bounds();
-                ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
-                    lifetime,
-                    bounds,
-                })
-            } else if self.check_type() {
-                match self.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
-                    struct_, pred_lo, where_sp,
-                )? {
-                    PredicateKindOrStructBody::PredicateKind(kind) => kind,
-                    PredicateKindOrStructBody::StructBody(body) => {
-                        tuple_struct_body = Some(body);
-                        break;
-                    }
+            let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
+                for attr in &attrs {
+                    self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
                 }
-            } else {
-                break;
-            };
-            where_clause.predicates.push(ast::WherePredicate {
-                kind,
-                id: DUMMY_NODE_ID,
-                span: pred_lo.to(self.prev_token.span),
-            });
+                let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
+                    let lifetime = this.expect_lifetime();
+                    // Bounds starting with a colon are mandatory, but possibly empty.
+                    this.expect(exp!(Colon))?;
+                    let bounds = this.parse_lt_param_bounds();
+                    Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
+                        lifetime,
+                        bounds,
+                    }))
+                } else if this.check_type() {
+                    match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
+                        struct_, pred_lo, where_sp,
+                    )? {
+                        PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
+                        PredicateKindOrStructBody::StructBody(body) => {
+                            tuple_struct_body = Some(body);
+                            None
+                        }
+                    }
+                } else {
+                    None
+                };
+                let predicate = kind.map(|kind| ast::WherePredicate {
+                    attrs,
+                    kind,
+                    id: DUMMY_NODE_ID,
+                    span: pred_lo.to(this.prev_token.span),
+                    is_placeholder: false,
+                });
+                Ok((predicate, Trailing::No, UsePreAttrPos::No))
+            })?;
+            match predicate {
+                Some(predicate) => where_clause.predicates.push(predicate),
+                None => break,
+            }
 
             let prev_token = self.prev_token.span;
             let ate_comma = self.eat(exp!(Comma));
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 5765a5b5315..3f642a7ac1f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -382,7 +382,7 @@ impl<'a> Parser<'a> {
 
     /// Are we sure this could not possibly be a macro invocation?
     fn isnt_macro_invocation(&mut self) -> bool {
-        self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::PathSep)
+        self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
     }
 
     /// Recover on encountering a struct, enum, or method definition where the user
@@ -480,7 +480,7 @@ impl<'a> Parser<'a> {
     /// Parses an item macro, e.g., `item!();`.
     fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
         let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
-        self.expect(exp!(Not))?; // `!`
+        self.expect(exp!(Bang))?; // `!`
         match self.parse_delim_args() {
             // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
             Ok(args) => {
@@ -540,7 +540,7 @@ impl<'a> Parser<'a> {
 
     fn parse_polarity(&mut self) -> ast::ImplPolarity {
         // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
-        if self.check(exp!(Not)) && self.look_ahead(1, |t| t.can_begin_type()) {
+        if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
             self.bump(); // `!`
             ast::ImplPolarity::Negative(self.prev_token.span)
         } else {
@@ -1293,7 +1293,7 @@ impl<'a> Parser<'a> {
                 if token.is_keyword(kw::Move) {
                     return true;
                 }
-                matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
+                matches!(token.kind, token::Or | token::OrOr)
             })
         } else {
             // `$qual static`
@@ -1579,7 +1579,7 @@ impl<'a> Parser<'a> {
             }
             let ident = this.parse_field_ident("enum", vlo)?;
 
-            if this.token == token::Not {
+            if this.token == token::Bang {
                 if let Err(err) = this.unexpected() {
                     err.with_note(fluent::parse_macro_expands_to_enum_variant).emit();
                 }
@@ -1814,7 +1814,7 @@ impl<'a> Parser<'a> {
             let attrs = p.parse_outer_attributes()?;
             p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
                 let mut snapshot = None;
-                if p.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
+                if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
                     // Account for `<<<<<<<` diff markers. We can't proactively error here because
                     // that can be a valid type start, so we snapshot and reparse only we've
                     // encountered another parse error.
@@ -2034,7 +2034,7 @@ impl<'a> Parser<'a> {
         attrs: AttrVec,
     ) -> PResult<'a, FieldDef> {
         let name = self.parse_field_ident(adt_ty, lo)?;
-        if self.token == token::Not {
+        if self.token == token::Bang {
             if let Err(mut err) = self.unexpected() {
                 // Encounter the macro invocation
                 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
@@ -2184,7 +2184,7 @@ impl<'a> Parser<'a> {
         if self.check_keyword(exp!(MacroRules)) {
             let macro_rules_span = self.token.span;
 
-            if self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) {
+            if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
                 return IsMacroRulesItem::Yes { has_bang: true };
             } else if self.look_ahead(1, |t| (t.is_ident())) {
                 // macro_rules foo
@@ -2209,11 +2209,11 @@ impl<'a> Parser<'a> {
         self.expect_keyword(exp!(MacroRules))?; // `macro_rules`
 
         if has_bang {
-            self.expect(exp!(Not))?; // `!`
+            self.expect(exp!(Bang))?; // `!`
         }
         let ident = self.parse_ident()?;
 
-        if self.eat(exp!(Not)) {
+        if self.eat(exp!(Bang)) {
             // Handle macro_rules! foo!
             let span = self.prev_token.span;
             self.dcx().emit_err(errors::MacroNameRemoveBang { span });
@@ -3011,7 +3011,7 @@ impl<'a> Parser<'a> {
         // else is parsed as a normal function parameter list, so some lookahead is required.
         let eself_lo = self.token.span;
         let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
-            token::BinOp(token::And) => {
+            token::And => {
                 let eself = if is_isolated_self(self, 1) {
                     // `&self`
                     self.bump();
@@ -3041,12 +3041,12 @@ impl<'a> Parser<'a> {
                 (eself, self_ident, hi)
             }
             // `*self`
-            token::BinOp(token::Star) if is_isolated_self(self, 1) => {
+            token::Star if is_isolated_self(self, 1) => {
                 self.bump();
                 recover_self_ptr(self)?
             }
             // `*mut self` and `*const self`
-            token::BinOp(token::Star)
+            token::Star
                 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
             {
                 self.bump();
@@ -3077,7 +3077,7 @@ impl<'a> Parser<'a> {
                 }
                 _ => 0,
             },
-            token::BinOp(token::And) | token::AndAnd => 1,
+            token::And | token::AndAnd => 1,
             _ if self.token.is_keyword(kw::Mut) => 1,
             _ => 0,
         };
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 00282ef8679..7dabc28c645 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -813,9 +813,9 @@ impl<'a> Parser<'a> {
         self.is_keyword_ahead(0, &[kw::Const])
             && self.look_ahead(1, |t| match &t.kind {
                 // async closures do not work with const closures, so we do not parse that here.
-                token::Ident(kw::Move | kw::Static, IdentIsRaw::No)
-                | token::OrOr
-                | token::BinOp(token::Or) => true,
+                token::Ident(kw::Move | kw::Static, IdentIsRaw::No) | token::OrOr | token::Or => {
+                    true
+                }
                 _ => false,
             })
     }
@@ -1651,7 +1651,7 @@ impl<'a> Parser<'a> {
     /// `::{` or `::*`
     fn is_import_coupler(&mut self) -> bool {
         self.check_path_sep_and_look_ahead(|t| {
-            matches!(t.kind, token::OpenDelim(Delimiter::Brace) | token::BinOp(token::Star))
+            matches!(t.kind, token::OpenDelim(Delimiter::Brace) | token::Star)
         })
     }
 
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 40f2e228b24..ec14c5718da 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -3,7 +3,7 @@ use std::ops::Bound;
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::NtPatKind::*;
-use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, MetaVarKind, Token};
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
@@ -358,7 +358,7 @@ impl<'a> Parser<'a> {
             )
         });
         match (is_end_ahead, &self.token.kind) {
-            (true, token::BinOp(token::Or) | token::OrOr) => {
+            (true, token::Or | token::OrOr) => {
                 // A `|` or possibly `||` token shouldn't be here. Ban it.
                 self.dcx().emit_err(TrailingVertNotAllowed {
                     span: self.token.span,
@@ -432,7 +432,11 @@ impl<'a> Parser<'a> {
         // `[` is included for indexing operations,
         // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`),
         // `as` is included for type casts
-        let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or)
+        let has_trailing_operator = matches!(
+                self.token.kind,
+                token::Plus | token::Minus | token::Star | token::Slash | token::Percent
+                | token::Caret | token::And | token::Shl | token::Shr // excludes `Or`
+            )
             || self.token == token::Question
             || (self.token == token::OpenDelim(Delimiter::Bracket)
                 && self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket))) // excludes `[]`
@@ -763,7 +767,7 @@ impl<'a> Parser<'a> {
             self.recover_dotdotdot_rest_pat(lo)
         } else if let Some(form) = self.parse_range_end() {
             self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
-        } else if self.eat(exp!(Not)) {
+        } else if self.eat(exp!(Bang)) {
             // Parse `!`
             self.psess.gated_spans.gate(sym::never_patterns, self.prev_token.span);
             PatKind::Never
@@ -819,7 +823,7 @@ impl<'a> Parser<'a> {
             };
             let span = lo.to(self.prev_token.span);
 
-            if qself.is_none() && self.check(exp!(Not)) {
+            if qself.is_none() && self.check(exp!(Bang)) {
                 self.parse_pat_mac_invoc(path)?
             } else if let Some(form) = self.parse_range_end() {
                 let begin = self.mk_expr(span, ExprKind::Path(qself, path));
@@ -1255,7 +1259,7 @@ impl<'a> Parser<'a> {
             || self.look_ahead(dist, |t| {
                 t.is_path_start() // e.g. `MY_CONST`;
                 || *t == token::Dot // e.g. `.5` for recovery;
-                || matches!(t.kind, token::Literal(..) | token::BinOp(token::Minus))
+                || matches!(t.kind, token::Literal(..) | token::Minus)
                 || t.is_bool_lit()
                 || t.is_whole_expr()
                 || t.is_lifetime() // recover `'a` instead of `'a'`
@@ -1331,7 +1335,7 @@ impl<'a> Parser<'a> {
             | token::OpenDelim(Delimiter::Brace) // A struct pattern.
             | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
             | token::PathSep // A tuple / struct variant pattern.
-            | token::Not)) // A macro expanding to a pattern.
+            | token::Bang)) // A macro expanding to a pattern.
     }
 
     /// Parses `ident` or `ident @ pat`.
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 8091dfa2a4a..9c6830c3672 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -305,10 +305,7 @@ impl<'a> Parser<'a> {
         let is_args_start = |token: &Token| {
             matches!(
                 token.kind,
-                token::Lt
-                    | token::BinOp(token::Shl)
-                    | token::OpenDelim(Delimiter::Parenthesis)
-                    | token::LArrow
+                token::Lt | token::Shl | token::OpenDelim(Delimiter::Parenthesis) | token::LArrow
             )
         };
         let check_args_start = |this: &mut Self| {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index a2699b077fc..3a9dc5ce798 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -176,7 +176,7 @@ impl<'a> Parser<'a> {
         let stmt = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
             let path = this.parse_path(PathStyle::Expr)?;
 
-            if this.eat(exp!(Not)) {
+            if this.eat(exp!(Bang)) {
                 let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
                 return Ok((
                     stmt_mac,
@@ -442,7 +442,16 @@ impl<'a> Parser<'a> {
     /// Parses the RHS of a local variable declaration (e.g., `= 14;`).
     fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
         let eq_consumed = match self.token.kind {
-            token::BinOpEq(..) => {
+            token::PlusEq
+            | token::MinusEq
+            | token::StarEq
+            | token::SlashEq
+            | token::PercentEq
+            | token::CaretEq
+            | token::AndEq
+            | token::OrEq
+            | token::ShlEq
+            | token::ShrEq => {
                 // Recover `let x <op>= 1` as `let x = 1` We must not use `+ BytePos(1)` here
                 // because `<op>` can be a multi-byte lookalike that was recovered, e.g. `➖=` (the
                 // `➖` is a U+2796 Heavy Minus Sign Unicode Character) that was recovered as a
@@ -688,7 +697,7 @@ impl<'a> Parser<'a> {
             if self.token == token::Eof {
                 break;
             }
-            if self.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
+            if self.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
                 // Account for `<<<<<<<` diff markers. We can't proactively error here because
                 // that can be a valid path start, so we snapshot and reparse only we've
                 // encountered another parse error.
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 8b8c81a77a0..471966d086d 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2291,7 +2291,7 @@ fn string_to_tts_macro() {
                     Token { kind: token::Ident(name_macro_rules, IdentIsRaw::No), .. },
                     _,
                 ),
-                TokenTree::Token(Token { kind: token::Not, .. }, _),
+                TokenTree::Token(Token { kind: token::Bang, .. }, _),
                 TokenTree::Token(Token { kind: token::Ident(name_zip, IdentIsRaw::No), .. }, _),
                 TokenTree::Delimited(.., macro_delim, macro_tts),
             ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => {
diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs
index 40631d9154d..110546d0ba6 100644
--- a/compiler/rustc_parse/src/parser/token_type.rs
+++ b/compiler/rustc_parse/src/parser/token_type.rs
@@ -25,7 +25,7 @@ pub enum TokenType {
     Gt,
     AndAnd,
     OrOr,
-    Not,
+    Bang,
     Tilde,
 
     // BinOps
@@ -172,7 +172,7 @@ impl TokenType {
             Gt,
             AndAnd,
             OrOr,
-            Not,
+            Bang,
             Tilde,
 
             Plus,
@@ -366,7 +366,7 @@ impl TokenType {
             TokenType::Gt => "`>`",
             TokenType::AndAnd => "`&&`",
             TokenType::OrOr => "`||`",
-            TokenType::Not => "`!`",
+            TokenType::Bang => "`!`",
             TokenType::Tilde => "`~`",
 
             TokenType::Plus => "`+`",
@@ -445,12 +445,6 @@ macro_rules! exp {
             token_type: $crate::parser::token_type::TokenType::$tok
         }
     };
-    (@binop, $op:ident) => {
-        $crate::parser::token_type::ExpTokenPair {
-            tok: &rustc_ast::token::BinOp(rustc_ast::token::BinOpToken::$op),
-            token_type: $crate::parser::token_type::TokenType::$op,
-        }
-    };
     (@open, $delim:ident, $token_type:ident) => {
         $crate::parser::token_type::ExpTokenPair {
             tok: &rustc_ast::token::OpenDelim(rustc_ast::token::Delimiter::$delim),
@@ -485,8 +479,13 @@ macro_rules! exp {
     (Gt)             => { exp!(@tok, Gt) };
     (AndAnd)         => { exp!(@tok, AndAnd) };
     (OrOr)           => { exp!(@tok, OrOr) };
-    (Not)            => { exp!(@tok, Not) };
+    (Bang)           => { exp!(@tok, Bang) };
     (Tilde)          => { exp!(@tok, Tilde) };
+    (Plus)           => { exp!(@tok, Plus) };
+    (Minus)          => { exp!(@tok, Minus) };
+    (Star)           => { exp!(@tok, Star) };
+    (And)            => { exp!(@tok, And) };
+    (Or)             => { exp!(@tok, Or) };
     (At)             => { exp!(@tok, At) };
     (Dot)            => { exp!(@tok, Dot) };
     (DotDot)         => { exp!(@tok, DotDot) };
@@ -502,12 +501,6 @@ macro_rules! exp {
     (Question)       => { exp!(@tok, Question) };
     (Eof)            => { exp!(@tok, Eof) };
 
-    (Plus)           => { exp!(@binop, Plus) };
-    (Minus)          => { exp!(@binop, Minus) };
-    (Star)           => { exp!(@binop, Star) };
-    (And)            => { exp!(@binop, And) };
-    (Or)             => { exp!(@binop, Or) };
-
     (OpenParen)      => { exp!(@open,  Parenthesis, OpenParen) };
     (OpenBrace)      => { exp!(@open,  Brace,       OpenBrace) };
     (OpenBracket)    => { exp!(@open,  Bracket,     OpenBracket) };
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 18af0a1c79a..b45ebae079c 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
@@ -86,7 +86,7 @@ enum AllowCVariadic {
 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
 /// that `IDENT` is not the ident of a fn trait.
 fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
-    t == &token::PathSep || t == &token::Lt || t == &token::BinOp(token::Shl)
+    t == &token::PathSep || t == &token::Lt || t == &token::Shl
 }
 
 fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
@@ -260,7 +260,7 @@ impl<'a> Parser<'a> {
         let mut impl_dyn_multi = false;
         let kind = if self.check(exp!(OpenParen)) {
             self.parse_ty_tuple_or_parens(lo, allow_plus)?
-        } else if self.eat(exp!(Not)) {
+        } else if self.eat(exp!(Bang)) {
             // Never type `!`
             TyKind::Never
         } else if self.eat(exp!(Star)) {
@@ -399,7 +399,7 @@ impl<'a> Parser<'a> {
         let mut trailing_plus = false;
         let (ts, trailing) = self.parse_paren_comma_seq(|p| {
             let ty = p.parse_ty()?;
-            trailing_plus = p.prev_token == TokenKind::BinOp(token::Plus);
+            trailing_plus = p.prev_token == TokenKind::Plus;
             Ok(ty)
         })?;
 
@@ -735,7 +735,7 @@ impl<'a> Parser<'a> {
         // Always parse bounds greedily for better error recovery.
         let bounds = self.parse_generic_bounds()?;
 
-        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::BinOp(token::Plus);
+        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
 
         Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
     }
@@ -747,11 +747,7 @@ impl<'a> Parser<'a> {
         self.expect_lt()?;
         let (args, _, _) = self.parse_seq_to_before_tokens(
             &[exp!(Gt)],
-            &[
-                &TokenKind::Ge,
-                &TokenKind::BinOp(BinOpToken::Shr),
-                &TokenKind::BinOpEq(BinOpToken::Shr),
-            ],
+            &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
             SeqSep::trailing_allowed(exp!(Comma)),
             |self_| {
                 if self_.check_keyword(exp!(SelfUpper)) {
@@ -781,7 +777,7 @@ impl<'a> Parser<'a> {
         self.check_keyword(exp!(Dyn))
             && (self.token.uninterpolated_span().at_least_rust_2018()
                 || self.look_ahead(1, |t| {
-                    (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::BinOp(token::Star))
+                    (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
                         && !can_continue_type_after_non_fn_ident(t)
                 }))
     }
@@ -803,7 +799,7 @@ impl<'a> Parser<'a> {
 
         // Always parse bounds greedily for better error recovery.
         let bounds = self.parse_generic_bounds()?;
-        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::BinOp(token::Plus);
+        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
         Ok(TyKind::TraitObject(bounds, syntax))
     }
 
@@ -821,7 +817,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, TyKind> {
         // Simple path
         let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
-        if self.eat(exp!(Not)) {
+        if self.eat(exp!(Bang)) {
             // Macro invocation in type position
             Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
@@ -874,7 +870,7 @@ impl<'a> Parser<'a> {
     fn can_begin_bound(&mut self) -> bool {
         self.check_path()
             || self.check_lifetime()
-            || self.check(exp!(Not))
+            || self.check(exp!(Bang))
             || self.check(exp!(Question))
             || self.check(exp!(Tilde))
             || self.check_keyword(exp!(For))
@@ -1025,7 +1021,7 @@ impl<'a> Parser<'a> {
 
         let polarity = if self.eat(exp!(Question)) {
             BoundPolarity::Maybe(self.prev_token.span)
-        } else if self.eat(exp!(Not)) {
+        } else if self.eat(exp!(Bang)) {
             self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
             BoundPolarity::Negative(self.prev_token.span)
         } else {
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index b65430c3480..ed498d9d344 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -779,6 +779,10 @@ passes_unstable_attr_for_already_stable_feature =
     .item = the stability attribute annotates this item
     .help = consider removing the attribute
 
+passes_unsupported_attributes_in_where =
+    most attributes are not supported in `where` clauses
+    .help = only `#[cfg]` and `#[cfg_attr]` are supported
+
 passes_unused =
     unused attribute
     .suggestion = remove this attribute
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5ada289cc20..91916b8f5fc 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -14,6 +14,7 @@ use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
 use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{
@@ -257,6 +258,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::coroutine, ..] => {
                             self.check_coroutine(attr, target);
                         }
+                        [sym::type_const, ..] => {
+                            self.check_type_const(hir_id,attr, target);
+                        }
                         [sym::linkage, ..] => self.check_linkage(attr, span, target),
                         [sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent(attr.span(), span, attrs),
                         [
@@ -919,7 +923,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             | Target::Arm
             | Target::ForeignMod
             | Target::Closure
-            | Target::Impl => Some(target.name()),
+            | Target::Impl
+            | Target::WherePredicate => Some(target.name()),
             Target::ExternCrate
             | Target::Use
             | Target::Static
@@ -2518,6 +2523,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
+    fn check_type_const(&self, hir_id: HirId, attr: &Attribute, target: Target) {
+        let tcx = self.tcx;
+        if target == Target::AssocConst
+            && let parent = tcx.parent(hir_id.expect_owner().to_def_id())
+            && self.tcx.def_kind(parent) == DefKind::Trait
+        {
+            return;
+        } else {
+            self.dcx()
+                .struct_span_err(
+                    attr.span(),
+                    "`#[type_const]` must only be applied to trait associated constants",
+                )
+                .emit();
+        }
+    }
+
     fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
             Target::Fn
@@ -2614,6 +2636,32 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         intravisit::walk_item(self, item)
     }
 
+    fn visit_where_predicate(&mut self, where_predicate: &'tcx hir::WherePredicate<'tcx>) {
+        // FIXME(where_clause_attrs): Currently, as the following check shows,
+        // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
+        // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
+        // in where clauses. After that, only `self.check_attributes` should be enough.
+        const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr];
+        let spans = self
+            .tcx
+            .hir()
+            .attrs(where_predicate.hir_id)
+            .iter()
+            .filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym)))
+            .map(|attr| attr.span())
+            .collect::<Vec<_>>();
+        if !spans.is_empty() {
+            self.tcx.dcx().emit_err(errors::UnsupportedAttributesInWhere { span: spans.into() });
+        }
+        self.check_attributes(
+            where_predicate.hir_id,
+            where_predicate.span,
+            Target::WherePredicate,
+            None,
+        );
+        intravisit::walk_where_predicate(self, where_predicate)
+    }
+
     fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
         let target = Target::from_generic_param(generic_param);
         self.check_attributes(generic_param.hir_id, generic_param.span, target, None);
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 9bb9b2353dc..b8359c27e53 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1909,3 +1909,11 @@ pub(crate) struct RustcConstStableIndirectPairing {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(passes_unsupported_attributes_in_where)]
+#[help]
+pub(crate) struct UnsupportedAttributesInWhere {
+    #[primary_span]
+    pub span: MultiSpan,
+}
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index e11123dff26..3b47e7eba0f 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -1,9 +1,9 @@
 use std::fmt::Debug;
 use std::hash::Hash;
+use std::sync::OnceLock;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sharded::{self, Sharded};
-use rustc_data_structures::sync::OnceLock;
 pub use rustc_data_structures::vec_cache::VecCache;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_index::Idx;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index a8c2aa98cd0..37b305d0a8b 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -477,8 +477,8 @@ fn remove_cycle(
 /// Detects query cycles by using depth first search over all active query jobs.
 /// If a query cycle is found it will break the cycle by finding an edge which
 /// uses a query latch and then resuming that waiter.
-/// There may be multiple cycles involved in a deadlock, so this searches
-/// all active queries for cycles before finally resuming all the waiters at once.
+/// There may be multiple cycles involved in a deadlock, but we only search
+/// one cycle at a call and resume one waiter at once. See `FIXME` below.
 pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) {
     let mut wakelist = Vec::new();
     let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
@@ -488,6 +488,19 @@ pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry)
     while jobs.len() > 0 {
         if remove_cycle(&query_map, &mut jobs, &mut wakelist) {
             found_cycle = true;
+
+            // FIXME(#137731): Resume all the waiters at once may cause deadlocks,
+            // so we resume one waiter at a call for now. It's still unclear whether
+            // it's due to possible issues in rustc-rayon or instead in the handling
+            // of query cycles.
+            // This seem to only appear when multiple query cycles errors
+            // are involved, so this reduction in parallelism, while suboptimal, is not
+            // universal and only the deadlock handler will encounter these cases.
+            // The workaround shows loss of potential gains, but there still are big
+            // improvements in the common case, and no regressions compared to the
+            // single-threaded case. More investigation is still needed, and once fixed,
+            // we can wake up all the waiters up.
+            break;
         }
     }
 
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 87f7eda391d..42fe01b1c84 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1529,6 +1529,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         visit::walk_variant(self, variant);
     }
 
+    fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
+        if p.is_placeholder {
+            self.visit_invoc(p.id);
+        } else {
+            visit::walk_where_predicate(self, p);
+        }
+    }
+
     fn visit_crate(&mut self, krate: &'a ast::Crate) {
         if krate.is_placeholder {
             self.visit_invoc_in_module(krate.id);
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 9d78c71b76a..95d637b6b22 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -285,6 +285,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         });
     }
 
+    fn visit_where_predicate(&mut self, pred: &'a WherePredicate) {
+        if pred.is_placeholder {
+            self.visit_macro_invoc(pred.id)
+        } else {
+            visit::walk_where_predicate(self, pred)
+        }
+    }
+
     fn visit_variant_data(&mut self, data: &'a VariantData) {
         // The assumption here is that non-`cfg` macro expansion cannot change field indices.
         // It currently holds because only inert attributes are accepted on fields,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index f119ed55e7d..29b606b7a59 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -78,6 +78,7 @@ struct IsNeverPattern;
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum AnonConstKind {
     EnumDiscriminant,
+    FieldDefaultValue,
     InlineConst,
     ConstArg(IsRepeatExpr),
 }
@@ -1202,7 +1203,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                 if let TyKind::Path(None, ref path) = ty.kind
                     // We cannot disambiguate multi-segment paths right now as that requires type
                     // checking.
-                    && path.is_potential_trivial_const_arg()
+                    && path.is_potential_trivial_const_arg(false)
                 {
                     let mut check_ns = |ns| {
                         self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
@@ -1406,7 +1407,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         visit_opt!(self, visit_ident, ident);
         try_visit!(self.visit_ty(ty));
         if let Some(v) = &default {
-            self.resolve_anon_const(v, AnonConstKind::ConstArg(IsRepeatExpr::No));
+            self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue);
         }
     }
 }
@@ -4630,11 +4631,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             constant, anon_const_kind
         );
 
-        self.resolve_anon_const_manual(
-            constant.value.is_potential_trivial_const_arg(),
-            anon_const_kind,
-            |this| this.resolve_expr(&constant.value, None),
-        )
+        let is_trivial_const_arg = constant
+            .value
+            .is_potential_trivial_const_arg(self.r.tcx.features().min_generic_const_args());
+        self.resolve_anon_const_manual(is_trivial_const_arg, anon_const_kind, |this| {
+            this.resolve_expr(&constant.value, None)
+        })
     }
 
     /// There are a few places that we need to resolve an anon const but we did not parse an
@@ -4658,6 +4660,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             AnonConstKind::EnumDiscriminant => {
                 ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
             }
+            AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes,
             AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
             AnonConstKind::ConstArg(_) => {
                 if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {
@@ -4794,8 +4797,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     // Constant arguments need to be treated as AnonConst since
                     // that is how they will be later lowered to HIR.
                     if const_args.contains(&idx) {
+                        let is_trivial_const_arg = argument.is_potential_trivial_const_arg(
+                            self.r.tcx.features().min_generic_const_args(),
+                        );
                         self.resolve_anon_const_manual(
-                            argument.is_potential_trivial_const_arg(),
+                            is_trivial_const_arg,
                             AnonConstKind::ConstArg(IsRepeatExpr::No),
                             |this| this.resolve_expr(argument, None),
                         );
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 0e14e7671b1..42be92c0f8f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -3515,12 +3515,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         }
                     }
                 }
-
-                // Record as using the suggested resolution.
-                let (_, (_, res)) = in_scope_lifetimes[0];
-                for &lt in &lifetime_refs {
-                    self.r.lifetimes_res_map.insert(lt.id, res);
-                }
             }
             _ => {
                 let lifetime_spans: Vec<_> =
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7586c5766b5..e62a8fc0fc3 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -42,6 +42,32 @@ mod cfg;
 mod native_libs;
 pub mod sigpipe;
 
+pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
+    // tidy-alphabetical-start
+    ("all-target-specs-json", PrintKind::AllTargetSpecs),
+    ("calling-conventions", PrintKind::CallingConventions),
+    ("cfg", PrintKind::Cfg),
+    ("check-cfg", PrintKind::CheckCfg),
+    ("code-models", PrintKind::CodeModels),
+    ("crate-name", PrintKind::CrateName),
+    ("deployment-target", PrintKind::DeploymentTarget),
+    ("file-names", PrintKind::FileNames),
+    ("host-tuple", PrintKind::HostTuple),
+    ("link-args", PrintKind::LinkArgs),
+    ("native-static-libs", PrintKind::NativeStaticLibs),
+    ("relocation-models", PrintKind::RelocationModels),
+    ("split-debuginfo", PrintKind::SplitDebuginfo),
+    ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
+    ("sysroot", PrintKind::Sysroot),
+    ("target-cpus", PrintKind::TargetCPUs),
+    ("target-features", PrintKind::TargetFeatures),
+    ("target-libdir", PrintKind::TargetLibdir),
+    ("target-list", PrintKind::TargetList),
+    ("target-spec-json", PrintKind::TargetSpec),
+    ("tls-models", PrintKind::TlsModels),
+    // tidy-alphabetical-end
+];
+
 /// The different settings that the `-C strip` flag can have.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum Strip {
@@ -1508,6 +1534,13 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE
     )
 });
 
+static PRINT_KINDS_STRING: LazyLock<String> = LazyLock::new(|| {
+    format!(
+        "[{}]",
+        PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|")
+    )
+});
+
 /// Returns all rustc command line options, including metadata for
 /// each option, such as whether the option is stable.
 pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
@@ -1568,10 +1601,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "",
             "print",
             "Compiler information to print on stdout",
-            "[crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|\
-             target-list|target-cpus|target-features|relocation-models|code-models|\
-             tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
-             stack-protector-strategies|link-args|deployment-target]",
+            &PRINT_KINDS_STRING,
         ),
         opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
         opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
@@ -1999,32 +2029,6 @@ fn collect_print_requests(
         cg.target_feature = String::new();
     }
 
-    const PRINT_KINDS: &[(&str, PrintKind)] = &[
-        // tidy-alphabetical-start
-        ("all-target-specs-json", PrintKind::AllTargetSpecs),
-        ("calling-conventions", PrintKind::CallingConventions),
-        ("cfg", PrintKind::Cfg),
-        ("check-cfg", PrintKind::CheckCfg),
-        ("code-models", PrintKind::CodeModels),
-        ("crate-name", PrintKind::CrateName),
-        ("deployment-target", PrintKind::DeploymentTarget),
-        ("file-names", PrintKind::FileNames),
-        ("host-tuple", PrintKind::HostTuple),
-        ("link-args", PrintKind::LinkArgs),
-        ("native-static-libs", PrintKind::NativeStaticLibs),
-        ("relocation-models", PrintKind::RelocationModels),
-        ("split-debuginfo", PrintKind::SplitDebuginfo),
-        ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
-        ("sysroot", PrintKind::Sysroot),
-        ("target-cpus", PrintKind::TargetCPUs),
-        ("target-features", PrintKind::TargetFeatures),
-        ("target-libdir", PrintKind::TargetLibdir),
-        ("target-list", PrintKind::TargetList),
-        ("target-spec-json", PrintKind::TargetSpec),
-        ("tls-models", PrintKind::TlsModels),
-        // tidy-alphabetical-end
-    ];
-
     // We disallow reusing the same path in multiple prints, such as `--print
     // cfg=output.txt --print link-args=output.txt`, because outputs are printed
     // by disparate pieces of the compiler, and keeping track of which files
@@ -2883,14 +2887,6 @@ impl PpMode {
             | StableMir => true,
         }
     }
-    pub fn needs_hir(&self) -> bool {
-        use PpMode::*;
-        match *self {
-            Source(_) | AstTree | AstTreeExpanded => false,
-
-            Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | StableMir => true,
-        }
-    }
 
     pub fn needs_analysis(&self) -> bool {
         use PpMode::*;
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 9182789cf02..fcede379b89 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -34,6 +34,7 @@ pub enum NativeLibKind {
         as_needed: Option<bool>,
     },
     /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
+    /// On Linux, it refers to a generated shared library stub.
     RawDylib,
     /// A macOS-specific kind of dynamic libraries.
     Framework {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2a709b07255..522bccb1acb 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1625,6 +1625,7 @@ symbols! {
         quote,
         range_inclusive_new,
         raw_dylib,
+        raw_dylib_elf,
         raw_eq,
         raw_identifiers,
         raw_ref_op,
@@ -2083,6 +2084,7 @@ symbols! {
         type_ascribe,
         type_ascription,
         type_changing_struct_update,
+        type_const,
         type_id,
         type_ir_inherent,
         type_length_limit,
@@ -2234,6 +2236,7 @@ symbols! {
         wasm_abi,
         wasm_import_module,
         wasm_target_feature,
+        where_clause_attrs,
         while_let,
         windows,
         windows_subsystem,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 4fafd1ac350..a11f6f0df1c 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -169,7 +169,7 @@ impl<'tcx> SymbolMangler<'tcx> {
         Ok(())
     }
 
-    fn in_binder<T>(
+    fn wrap_binder<T>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
         print_value: impl FnOnce(&mut Self, &T) -> Result<(), PrintError>,
@@ -471,7 +471,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             ty::FnPtr(sig_tys, hdr) => {
                 let sig = sig_tys.with(hdr);
                 self.push("F");
-                self.in_binder(&sig, |cx, sig| {
+                self.wrap_binder(&sig, |cx, sig| {
                     if sig.safety.is_unsafe() {
                         cx.push("U");
                     }
@@ -554,7 +554,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         // [<Trait> [{<Projection>}]] [{<Auto>}]
         // Since any predicates after the first one shouldn't change the binders,
         // just put them all in the binders of the first.
-        self.in_binder(&predicates[0], |cx, _| {
+        self.wrap_binder(&predicates[0], |cx, _| {
             for predicate in predicates.iter() {
                 // It would be nice to be able to validate bound vars here, but
                 // projections can actually include bound vars from super traits
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index cc8162a2f27..72202129f5b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -43,7 +43,7 @@ use std::str::FromStr;
 use std::{fmt, io};
 
 use rustc_abi::{Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_fs_util::try_canonicalize;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -3535,6 +3535,59 @@ impl Target {
             s => s.clone(),
         }
     }
+
+    pub fn object_architecture(
+        &self,
+        unstable_target_features: &FxIndexSet<Symbol>,
+    ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
+        use object::Architecture;
+        Some(match self.arch.as_ref() {
+            "arm" => (Architecture::Arm, None),
+            "aarch64" => (
+                if self.pointer_width == 32 {
+                    Architecture::Aarch64_Ilp32
+                } else {
+                    Architecture::Aarch64
+                },
+                None,
+            ),
+            "x86" => (Architecture::I386, None),
+            "s390x" => (Architecture::S390x, None),
+            "mips" | "mips32r6" => (Architecture::Mips, None),
+            "mips64" | "mips64r6" => (Architecture::Mips64, None),
+            "x86_64" => (
+                if self.pointer_width == 32 {
+                    Architecture::X86_64_X32
+                } else {
+                    Architecture::X86_64
+                },
+                None,
+            ),
+            "powerpc" => (Architecture::PowerPc, None),
+            "powerpc64" => (Architecture::PowerPc64, None),
+            "riscv32" => (Architecture::Riscv32, None),
+            "riscv64" => (Architecture::Riscv64, None),
+            "sparc" => {
+                if unstable_target_features.contains(&sym::v8plus) {
+                    // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode
+                    (Architecture::Sparc32Plus, None)
+                } else {
+                    // Target uses V7 or V8, aka EM_SPARC
+                    (Architecture::Sparc, None)
+                }
+            }
+            "sparc64" => (Architecture::Sparc64, None),
+            "avr" => (Architecture::Avr, None),
+            "msp430" => (Architecture::Msp430, None),
+            "hexagon" => (Architecture::Hexagon, None),
+            "bpf" => (Architecture::Bpf, None),
+            "loongarch64" => (Architecture::LoongArch64, None),
+            "csky" => (Architecture::Csky, None),
+            "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
+            // Unsupported architecture.
+            _ => return None,
+        })
+    }
 }
 
 /// Either a target tuple string or a path to a JSON file.
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
index 03bae9b5977..3c1d18e0777 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "spe".into(),
             endian: Endian::Big,
-            features: "+secure-plt".into(),
+            features: "+secure-plt,+msync".into(),
             mcount: "_mcount".into(),
             ..base
         },
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
index df4fd75b0bd..30d0d9cb60a 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
@@ -26,6 +26,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "spe".into(),
             endian: Endian::Big,
+            features: "+msync".into(),
             mcount: "_mcount".into(),
             ..base
         },
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 65a85151bef..d05466bb484 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -461,6 +461,7 @@ const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
 static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("altivec", Unstable(sym::powerpc_target_feature), &[]),
+    ("msync", Unstable(sym::powerpc_target_feature), &[]),
     ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
     ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
     ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 847bd06bb01..42d37418fb8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -65,7 +65,9 @@ use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
 use rustc_middle::traits::PatternOriginExpr;
 use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
-use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, with_forced_trimmed_paths};
+use rustc_middle::ty::print::{
+    PrintError, PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths,
+};
 use rustc_middle::ty::{
     self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt,
@@ -835,7 +837,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let get_lifetimes = |sig| {
             use rustc_hir::def::Namespace;
             let (sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
-                .name_all_regions(sig)
+                .name_all_regions(sig, WrapBinderMode::ForAll)
                 .unwrap();
             let lts: Vec<String> =
                 reg.into_items().map(|(_, kind)| kind.to_string()).into_sorted_stable_ord();
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index d270b4cf96b..8c1df9b5113 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -3250,7 +3250,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         span: Span,
     ) -> Result<Diag<'a>, ErrorGuaranteed> {
-        if !self.tcx.features().generic_const_exprs() {
+        if !self.tcx.features().generic_const_exprs()
+            && !self.tcx.features().min_generic_const_args()
+        {
             let guar = self
                 .dcx()
                 .struct_span_err(span, "constant expression depends on a generic parameter")
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index b85c18c5312..d180c0be9d5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3126,8 +3126,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     Applicability::MachineApplicable,
                 );
             }
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
+            ObligationCauseCode::SizedConstOrStatic => {
+                err.note("statics and constants must have a statically known size");
             }
             ObligationCauseCode::InlineAsmSized => {
                 err.note("all inline asm arguments must have a statically known size");
diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs
index 55171754618..068e90b00b8 100644
--- a/compiler/rustc_trait_selection/src/regions.rs
+++ b/compiler/rustc_trait_selection/src/regions.rs
@@ -17,13 +17,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
     ) -> Self {
-        Self::new_with_implied_bounds_compat(
-            infcx,
-            body_id,
-            param_env,
-            assumed_wf_tys,
-            !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat,
-        )
+        Self::new_with_implied_bounds_compat(infcx, body_id, param_env, assumed_wf_tys, false)
     }
 
     fn new_with_implied_bounds_compat(
@@ -31,7 +25,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
         body_id: LocalDefId,
         param_env: ty::ParamEnv<'tcx>,
         assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
-        implied_bounds_compat: bool,
+        disable_implied_bounds_hack: bool,
     ) -> Self {
         let mut bounds = vec![];
 
@@ -59,11 +53,11 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
         OutlivesEnvironment::from_normalized_bounds(
             param_env,
             bounds,
-            infcx.implied_bounds_tys_with_compat(
+            infcx.implied_bounds_tys(
                 body_id,
                 param_env,
                 assumed_wf_tys,
-                implied_bounds_compat,
+                disable_implied_bounds_hack,
             ),
         )
     }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index bdee6ca2afe..75f53b063d1 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -85,6 +85,12 @@ pub fn is_const_evaluatable<'tcx>(
             }
             _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
         }
+    } else if tcx.features().min_generic_const_args() {
+        // This is a sanity check to make sure that non-generics consts are checked to
+        // be evaluatable in case they aren't cchecked elsewhere. This will NOT error
+        // if the const uses generics, as desired.
+        crate::traits::evaluate_const(infcx, unexpanded_ct, param_env);
+        Ok(())
     } else {
         let uv = match unexpanded_ct.kind() {
             ty::ConstKind::Unevaluated(uv) => uv,
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 18932695807..68983ef80fa 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -36,7 +36,7 @@ fn implied_outlives_bounds<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
     ty: Ty<'tcx>,
-    compat: bool,
+    disable_implied_bounds_hack: bool,
 ) -> Vec<OutlivesBound<'tcx>> {
     let ty = infcx.resolve_vars_if_possible(ty);
     let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty);
@@ -52,11 +52,8 @@ fn implied_outlives_bounds<'a, 'tcx>(
     let mut canonical_var_values = OriginalQueryValues::default();
     let input = ImpliedOutlivesBounds { ty };
     let canonical = infcx.canonicalize_query(param_env.and(input), &mut canonical_var_values);
-    let implied_bounds_result = if compat {
-        infcx.tcx.implied_outlives_bounds_compat(canonical)
-    } else {
-        infcx.tcx.implied_outlives_bounds(canonical)
-    };
+    let implied_bounds_result =
+        infcx.tcx.implied_outlives_bounds((canonical, disable_implied_bounds_hack));
     let Ok(canonical_result) = implied_bounds_result else {
         return vec![];
     };
@@ -110,14 +107,15 @@ fn implied_outlives_bounds<'a, 'tcx>(
 impl<'tcx> InferCtxt<'tcx> {
     /// Do *NOT* call this directly. You probably want to construct a `OutlivesEnvironment`
     /// instead if you're interested in the implied bounds for a given signature.
-    fn implied_bounds_tys_with_compat<Tys: IntoIterator<Item = Ty<'tcx>>>(
+    fn implied_bounds_tys<Tys: IntoIterator<Item = Ty<'tcx>>>(
         &self,
         body_id: LocalDefId,
         param_env: ParamEnv<'tcx>,
         tys: Tys,
-        compat: bool,
+        disable_implied_bounds_hack: bool,
     ) -> impl Iterator<Item = OutlivesBound<'tcx>> {
-        tys.into_iter()
-            .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, ty, compat))
+        tys.into_iter().flat_map(move |ty| {
+            implied_outlives_bounds(self, param_env, body_id, ty, disable_implied_bounds_hack)
+        })
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index de5aaa5bd97..4d9cf6620d6 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1232,8 +1232,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // why we special case object types.
                 false
             }
-            ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
-            | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
+            ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
                 // These traits have no associated types.
                 selcx.tcx().dcx().span_delayed_bug(
                     obligation.cause.span,
@@ -1325,8 +1324,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
         }
         ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
         | ImplSource::Param(..)
-        | ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
-        | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
+        | ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index ec0b7903396..f98529860ff 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,15 +1,16 @@
+use std::ops::ControlFlow;
+
+use rustc_infer::infer::RegionObligation;
 use rustc_infer::infer::canonical::CanonicalQueryInput;
-use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
 use rustc_middle::infer::canonical::CanonicalQueryResponse;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitable, TypeVisitor};
 use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::{DUMMY_SP, Span, sym};
 use rustc_type_ir::outlives::{Component, push_outlives_components};
 use smallvec::{SmallVec, smallvec};
-use tracing::debug;
 
 use crate::traits::query::NoSolution;
 use crate::traits::{ObligationCtxt, wf};
@@ -35,11 +36,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
         tcx: TyCtxt<'tcx>,
         canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
-        if tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
-            tcx.implied_outlives_bounds(canonicalized)
-        } else {
-            tcx.implied_outlives_bounds_compat(canonicalized)
-        }
+        tcx.implied_outlives_bounds((canonicalized, false))
     }
 
     fn perform_locally_with_next_solver(
@@ -47,11 +44,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
         key: ParamEnvAnd<'tcx, Self>,
         span: Span,
     ) -> Result<Self::QueryResponse, NoSolution> {
-        if ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
-            compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty, span)
-        } else {
-            compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty, span)
-        }
+        compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty, span, false)
     }
 }
 
@@ -60,18 +53,15 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
     span: Span,
+    disable_implied_bounds_hack: bool,
 ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
-    let normalize_op = |ty| -> Result<_, NoSolution> {
+    let normalize_ty = |ty| -> Result<_, NoSolution> {
         // We must normalize the type so we can compute the right outlives components.
         // for example, if we have some constrained param type like `T: Trait<Out = U>`,
         // and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
         let ty = ocx
             .deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty)
             .map_err(|_| NoSolution)?;
-        if !ocx.select_all_or_error().is_empty() {
-            return Err(NoSolution);
-        }
-        let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty);
         Ok(ty)
     };
 
@@ -81,7 +71,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
     // guaranteed to be a subset of the original type, so we need to store the
     // WF args we've computed in a set.
     let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
-    let mut wf_args = vec![ty.into(), normalize_op(ty)?.into()];
+    let mut wf_args = vec![ty.into(), normalize_ty(ty)?.into()];
 
     let mut outlives_bounds: Vec<OutlivesBound<'tcx>> = vec![];
 
@@ -96,8 +86,14 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
                 .into_iter()
                 .flatten()
         {
-            assert!(!obligation.has_escaping_bound_vars());
-            let Some(pred) = obligation.predicate.kind().no_bound_vars() else {
+            let pred = ocx
+                .deeply_normalize(
+                    &ObligationCause::dummy_with_span(span),
+                    param_env,
+                    obligation.predicate,
+                )
+                .map_err(|_| NoSolution)?;
+            let Some(pred) = pred.kind().no_bound_vars() else {
                 continue;
             };
             match pred {
@@ -130,7 +126,6 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
                     ty_a,
                     r_b,
                 ))) => {
-                    let ty_a = normalize_op(ty_a)?;
                     let mut components = smallvec![];
                     push_outlives_components(ocx.infcx.tcx, ty_a, &mut components);
                     outlives_bounds.extend(implied_bounds_from_components(r_b, components))
@@ -139,141 +134,48 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
         }
     }
 
-    Ok(outlives_bounds)
-}
-
-pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
-    ocx: &ObligationCtxt<'_, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    span: Span,
-) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
-    let tcx = ocx.infcx.tcx;
-
-    // Sometimes when we ask what it takes for T: WF, we get back that
-    // U: WF is required; in that case, we push U onto this stack and
-    // process it next. Because the resulting predicates aren't always
-    // guaranteed to be a subset of the original type, so we need to store the
-    // WF args we've computed in a set.
-    let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
-    let mut wf_args = vec![ty.into()];
-
-    let mut outlives_bounds: Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> = vec![];
-
-    while let Some(arg) = wf_args.pop() {
-        if !checked_wf_args.insert(arg) {
-            continue;
+    // If we detect `bevy_ecs::*::ParamSet` in the WF args list (and `disable_implied_bounds_hack`
+    // or `-Zno-implied-bounds-compat` are not set), then use the registered outlives obligations
+    // as implied bounds.
+    if !disable_implied_bounds_hack
+        && !ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat
+        && ty.visit_with(&mut ContainsBevyParamSet { tcx: ocx.infcx.tcx }).is_break()
+    {
+        for RegionObligation { sup_type, sub_region, .. } in
+            ocx.infcx.take_registered_region_obligations()
+        {
+            let mut components = smallvec![];
+            push_outlives_components(ocx.infcx.tcx, sup_type, &mut components);
+            outlives_bounds.extend(implied_bounds_from_components(sub_region, components));
         }
+    }
 
-        // Compute the obligations for `arg` to be well-formed. If `arg` is
-        // an unresolved inference variable, just instantiated an empty set
-        // -- because the return type here is going to be things we *add*
-        // to the environment, it's always ok for this set to be smaller
-        // than the ultimate set. (Note: normally there won't be
-        // unresolved inference variables here anyway, but there might be
-        // during typeck under some circumstances.)
-        //
-        // FIXME(@lcnr): It's not really "always fine", having fewer implied
-        // bounds can be backward incompatible, e.g. #101951 was caused by
-        // us not dealing with inference vars in `TypeOutlives` predicates.
-        let obligations =
-            wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, span).unwrap_or_default();
+    Ok(outlives_bounds)
+}
 
-        for obligation in obligations {
-            debug!(?obligation);
-            assert!(!obligation.has_escaping_bound_vars());
+struct ContainsBevyParamSet<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
 
-            // While these predicates should all be implied by other parts of
-            // the program, they are still relevant as they may constrain
-            // inference variables, which is necessary to add the correct
-            // implied bounds in some cases, mostly when dealing with projections.
-            //
-            // Another important point here: we only register `Projection`
-            // predicates, since otherwise we might register outlives
-            // predicates containing inference variables, and we don't
-            // learn anything new from those.
-            if obligation.predicate.has_non_region_infer() {
-                match obligation.predicate.kind().skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-                    | ty::PredicateKind::AliasRelate(..) => {
-                        ocx.register_obligation(obligation.clone());
-                    }
-                    _ => {}
-                }
-            }
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> {
+    type Result = ControlFlow<()>;
 
-            let pred = match obligation.predicate.kind().no_bound_vars() {
-                None => continue,
-                Some(pred) => pred,
-            };
-            match pred {
-                // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
-                // if we ever support that
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-                | ty::PredicateKind::Subtype(..)
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-                | ty::PredicateKind::DynCompatible(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::ConstEquate(..)
-                | ty::PredicateKind::Ambiguous
-                | ty::PredicateKind::NormalizesTo(..)
-                | ty::PredicateKind::AliasRelate(..) => {}
-
-                // We need to search through *all* WellFormed predicates
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                    wf_args.push(arg);
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        // We only care to match `ParamSet<T>` or `&ParamSet<T>`.
+        match t.kind() {
+            ty::Adt(def, _) => {
+                if self.tcx.item_name(def.did()) == sym::ParamSet
+                    && self.tcx.crate_name(def.did().krate) == sym::bevy_ecs
+                {
+                    return ControlFlow::Break(());
                 }
-
-                // We need to register region relationships
-                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                    ty::OutlivesPredicate(r_a, r_b),
-                )) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
-
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                    ty_a,
-                    r_b,
-                ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
             }
+            ty::Ref(_, ty, _) => ty.visit_with(self)?,
+            _ => {}
         }
-    }
 
-    // This call to `select_all_or_error` is necessary to constrain inference variables, which we
-    // use further down when computing the implied bounds.
-    match ocx.select_all_or_error().as_slice() {
-        [] => (),
-        _ => return Err(NoSolution),
+        ControlFlow::Continue(())
     }
-
-    // We lazily compute the outlives components as
-    // `select_all_or_error` constrains inference variables.
-    let mut implied_bounds = Vec::new();
-    for ty::OutlivesPredicate(a, r_b) in outlives_bounds {
-        match a.unpack() {
-            ty::GenericArgKind::Lifetime(r_a) => {
-                implied_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a))
-            }
-            ty::GenericArgKind::Type(ty_a) => {
-                let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
-                // Need to manually normalize in the new solver as `wf::obligations` does not.
-                if ocx.infcx.next_trait_solver() {
-                    ty_a = ocx
-                        .deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty_a)
-                        .map_err(|_| NoSolution)?;
-                }
-                let mut components = smallvec![];
-                push_outlives_components(tcx, ty_a, &mut components);
-                implied_bounds.extend(implied_bounds_from_components(r_b, components))
-            }
-            ty::GenericArgKind::Const(_) => {
-                unreachable!("consts do not participate in outlives bounds")
-            }
-        }
-    }
-
-    Ok(implied_bounds)
 }
 
 /// When we have an implied bound that `T: 'a`, we can further break
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 11b6b826efe..a8d8003ead6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -1017,13 +1017,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-                if tys_a.len() == tys_b.len() {
-                    candidates.vec.push(BuiltinUnsizeCandidate);
-                }
-            }
-
             _ => {}
         };
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index a58317dd56d..6669d8525fa 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -7,7 +7,6 @@
 //! [rustc dev guide]:
 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 
-use std::iter;
 use std::ops::ControlFlow;
 
 use rustc_ast::Mutability;
@@ -410,7 +409,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let predicate = obligation.predicate.skip_binder();
 
         let mut assume = predicate.trait_ref.args.const_at(2);
-        // FIXME(min_generic_const_exprs): We should shallowly normalize this.
+        // FIXME(mgca): We should shallowly normalize this.
         if self.tcx().features().generic_const_exprs() {
             assume = crate::traits::evaluate_const(self.infcx, assume, obligation.param_env)
         }
@@ -1315,34 +1314,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
             }
 
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-                assert_eq!(tys_a.len(), tys_b.len());
-
-                // The last field of the tuple has to exist.
-                let (&a_last, a_mid) = tys_a.split_last().ok_or(Unimplemented)?;
-                let &b_last = tys_b.last().unwrap();
-
-                // Check that the source tuple with the target's
-                // last element is equal to the target.
-                let new_tuple =
-                    Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
-                let InferOk { mut obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(DefineOpaqueTypes::Yes, target, new_tuple)
-                    .map_err(|_| Unimplemented)?;
-
-                // Add a nested `T: Unsize<U>` predicate.
-                let last_unsize_obligation = obligation.with(
-                    tcx,
-                    ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
-                );
-                obligations.push(last_unsize_obligation);
-
-                ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
-            }
-
             _ => bug!("source: {source}, target: {target}"),
         })
     }
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 5f75e242a50..6fb483e6dac 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -10,38 +10,28 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{
-    compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner,
-};
+use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner;
 use rustc_trait_selection::traits::query::{CanonicalImpliedOutlivesBoundsGoal, NoSolution};
 
 pub(crate) fn provide(p: &mut Providers) {
-    *p = Providers { implied_outlives_bounds_compat, ..*p };
     *p = Providers { implied_outlives_bounds, ..*p };
 }
 
-fn implied_outlives_bounds_compat<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>,
-) -> Result<
-    &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
-    NoSolution,
-> {
-    tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
-        let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
-        compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty, DUMMY_SP)
-    })
-}
-
 fn implied_outlives_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
-    goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>,
+    (goal, disable_implied_bounds_hack): (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool),
 ) -> Result<
     &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
     NoSolution,
 > {
     tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
         let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
-        compute_implied_outlives_bounds_inner(ocx, param_env, ty, DUMMY_SP)
+        compute_implied_outlives_bounds_inner(
+            ocx,
+            param_env,
+            ty,
+            DUMMY_SP,
+            disable_implied_bounds_hack,
+        )
     })
 }
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index ae795ef2214..de2c3b63997 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -42,8 +42,6 @@ ty_utils_logical_op_not_supported = unsupported operation in generic constants,
 
 ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
 
-ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
-
 ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
 
 ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index e317768ff60..a726ebae6fe 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -436,10 +436,7 @@ fn fn_abi_sanity_check<'tcx>(
     ) {
         let tcx = cx.tcx();
 
-        if spec_abi == ExternAbi::Rust
-            || spec_abi == ExternAbi::RustCall
-            || spec_abi == ExternAbi::RustCold
-        {
+        if spec_abi.is_rustic_abi() {
             if arg.layout.is_zst() {
                 // Casting closures to function pointers depends on ZST closure types being
                 // omitted entirely in the calling convention.
@@ -687,7 +684,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
 
     let tcx = cx.tcx();
 
-    if abi == ExternAbi::Rust || abi == ExternAbi::RustCall || abi == ExternAbi::RustIntrinsic {
+    if abi.is_rustic_abi() {
         fn_abi.adjust_for_rust_abi(cx, abi);
 
         // Look up the deduced parameter attributes for this function, if we have its def ID and
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 5497d7d0bd2..8877bb45ceb 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -83,12 +83,6 @@ pub(crate) struct ZeroLengthSimdType<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_multiple_array_fields_simd_type)]
-pub(crate) struct MultipleArrayFieldsSimdType<'tcx> {
-    pub ty: Ty<'tcx>,
-}
-
-#[derive(Diagnostic)]
 #[diag(ty_utils_oversized_simd_type)]
 pub(crate) struct OversizedSimdType<'tcx> {
     pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index d059d6dcd13..6dc5a9c4a47 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -381,8 +381,7 @@ fn resolve_associated_item<'tcx>(
             }
         }
         traits::ImplSource::Param(..)
-        | traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
-        | traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None,
+        | traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => None,
     })
 }
 
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 1a82d171307..852d3fc58d8 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -28,9 +28,7 @@ use rustc_span::{Symbol, sym};
 use tracing::{debug, instrument, trace};
 use {rustc_abi as abi, rustc_hir as hir};
 
-use crate::errors::{
-    MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
-};
+use crate::errors::{NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType};
 
 mod invariant;
 
@@ -450,71 +448,26 @@ fn layout_of_uncached<'tcx>(
 
         // SIMD vector types.
         ty::Adt(def, args) if def.repr().simd() => {
-            if !def.is_struct() {
-                // Should have yielded E0517 by now.
-                let guar = tcx
-                    .dcx()
-                    .delayed_bug("#[repr(simd)] was applied to an ADT that is not a struct");
-                return Err(error(cx, LayoutError::ReferencesError(guar)));
-            }
-
-            let fields = &def.non_enum_variant().fields;
-
-            // Supported SIMD vectors are homogeneous ADTs with at least one field:
+            // Supported SIMD vectors are ADTs with a single array field:
             //
-            // * #[repr(simd)] struct S(T, T, T, T);
-            // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T }
             // * #[repr(simd)] struct S([T; 4])
             //
             // where T is a primitive scalar (integer/float/pointer).
-
-            // SIMD vectors with zero fields are not supported.
-            // (should be caught by typeck)
-            if fields.is_empty() {
-                tcx.dcx().emit_fatal(ZeroLengthSimdType { ty })
-            }
-
-            // Type of the first ADT field:
-            let f0_ty = fields[FieldIdx::ZERO].ty(tcx, args);
-
-            // Heterogeneous SIMD vectors are not supported:
-            // (should be caught by typeck)
-            for fi in fields {
-                if fi.ty(tcx, args) != f0_ty {
-                    let guar = tcx.dcx().delayed_bug(
-                        "#[repr(simd)] was applied to an ADT with heterogeneous field type",
-                    );
-                    return Err(error(cx, LayoutError::ReferencesError(guar)));
-                }
-            }
-
-            // 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 ty::Array(e_ty, _) = f0_ty.kind() {
-                // First ADT field is an array:
-
-                // SIMD vectors with multiple array fields are not supported:
-                // Can't be caught by typeck with a generic simd type.
-                if def.non_enum_variant().fields.len() != 1 {
-                    tcx.dcx().emit_fatal(MultipleArrayFieldsSimdType { ty });
-                }
-
-                // Extract the number of elements from the layout of the array field:
-                let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
-                    return Err(error(cx, LayoutError::Unknown(ty)));
-                };
-
-                (*e_ty, *count, true)
-            } else {
-                // First ADT field is not an array:
-                (f0_ty, def.non_enum_variant().fields.len() as _, false)
+            let Some(ty::Array(e_ty, e_len)) = def
+                .is_struct()
+                .then(|| &def.variant(FIRST_VARIANT).fields)
+                .filter(|fields| fields.len() == 1)
+                .map(|fields| *fields[FieldIdx::ZERO].ty(tcx, args).kind())
+            else {
+                // Invalid SIMD types should have been caught by typeck by now.
+                let guar = tcx.dcx().delayed_bug("#[repr(simd)] was applied to an invalid ADT");
+                return Err(error(cx, LayoutError::ReferencesError(guar)));
             };
 
+            let e_len = extract_const_value(cx, ty, e_len)?
+                .try_to_target_usize(tcx)
+                .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
+
             // SIMD vectors of zero length are not supported.
             // Additionally, lengths are capped at 2^16 as a fixed maximum backends must
             // support.
@@ -559,16 +512,12 @@ fn layout_of_uncached<'tcx>(
             };
             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 }
-            };
-
             tcx.mk_layout(LayoutData {
                 variants: Variants::Single { index: FIRST_VARIANT },
-                fields,
+                fields: FieldsShape::Arbitrary {
+                    offsets: [Size::ZERO].into(),
+                    memory_index: [0].into(),
+                },
                 backend_repr: abi,
                 largest_niche: e_ly.largest_niche,
                 uninhabited: false,
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index b93668b5111..6f37db1cb85 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -189,11 +189,6 @@ pub enum BuiltinImplSource {
     ///
     /// The index is only used for winnowing.
     TraitUpcasting(usize),
-    /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
-    ///
-    /// This can be removed when `feature(tuple_unsizing)` is stabilized, since we only
-    /// use it to detect when unsizing tuples in hir typeck.
-    TupleUnsizing,
 }
 
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs
index 8c6fd99f98a..2577c281ca4 100644
--- a/compiler/stable_mir/src/crate_def.rs
+++ b/compiler/stable_mir/src/crate_def.rs
@@ -10,6 +10,27 @@ use crate::{Crate, Symbol, with};
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)]
 pub struct DefId(pub(crate) usize);
 
+impl DefId {
+    /// Return fully qualified name of this definition
+    pub fn name(&self) -> Symbol {
+        with(|cx| cx.def_name(*self, false))
+    }
+
+    /// Return a trimmed name of this definition.
+    ///
+    /// This can be used to print more user friendly diagnostic messages.
+    ///
+    /// If a symbol name can only be imported from one place for a type, and as
+    /// long as it was not glob-imported anywhere in the current crate, we trim its
+    /// path and print only the name.
+    ///
+    /// For example, this function may shorten `std::vec::Vec` to just `Vec`,
+    /// as long as there is no other `Vec` importable anywhere.
+    pub fn trimmed_name(&self) -> Symbol {
+        with(|cx| cx.def_name(*self, true))
+    }
+}
+
 /// A trait for retrieving information about a particular definition.
 ///
 /// Implementors must provide the implementation of `def_id` which will be used to retrieve
@@ -19,24 +40,17 @@ pub trait CrateDef {
     fn def_id(&self) -> DefId;
 
     /// Return the fully qualified name of the current definition.
+    ///
+    /// See [`DefId::name`] for more details
     fn name(&self) -> Symbol {
-        let def_id = self.def_id();
-        with(|cx| cx.def_name(def_id, false))
+        self.def_id().name()
     }
 
     /// Return a trimmed name of this definition.
     ///
-    /// This can be used to print more user friendly diagnostic messages.
-    ///
-    /// If a symbol name can only be imported from one place for a type, and as
-    /// long as it was not glob-imported anywhere in the current crate, we trim its
-    /// path and print only the name.
-    ///
-    /// For example, this function may shorten `std::vec::Vec` to just `Vec`,
-    /// as long as there is no other `Vec` importable anywhere.
+    /// See [`DefId::trimmed_name`] for more details
     fn trimmed_name(&self) -> Symbol {
-        let def_id = self.def_id();
-        with(|cx| cx.def_name(def_id, true))
+        self.def_id().trimmed_name()
     }
 
     /// Return information about the crate where this definition is declared.
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 0b4cebadad1..70d42dfbfcb 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -48,10 +48,7 @@ pub type CrateNum = usize;
 
 impl Debug for DefId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("DefId")
-            .field("id", &self.0)
-            .field("name", &with(|cx| cx.def_name(*self, false)))
-            .finish()
+        f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish()
     }
 }
 
@@ -132,13 +129,21 @@ crate_def_with_ty! {
 }
 
 impl CrateItem {
-    /// This will return the body of an item.
-    ///
-    /// This will panic if no body is available.
-    pub fn body(&self) -> mir::Body {
+    /// This will return the body of an item or panic if it's not available.
+    pub fn expect_body(&self) -> mir::Body {
         with(|cx| cx.mir_body(self.0))
     }
 
+    /// Return the body of an item if available.
+    pub fn body(&self) -> Option<mir::Body> {
+        with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0)))
+    }
+
+    /// Check if a body is available for this item.
+    pub fn has_body(&self) -> bool {
+        with(|cx| cx.has_body(self.0))
+    }
+
     pub fn span(&self) -> Span {
         with(|cx| cx.span_of_an_item(self.0))
     }
@@ -159,8 +164,11 @@ impl CrateItem {
         with(|cx| cx.is_foreign_item(self.0))
     }
 
+    /// Emit MIR for this item body.
     pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
-        self.body().dump(w, &self.name())
+        self.body()
+            .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))?
+            .dump(w, &self.name())
     }
 }
 
diff --git a/config.example.toml b/config.example.toml
index 2e26c024865..ac5e491b4b5 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -189,6 +189,17 @@
 # The default stage to use for the `bench` subcommand
 #bench-stage = 2
 
+# A descriptive string to be appended to version output (e.g., `rustc --version`),
+# which is also used in places like debuginfo `DW_AT_producer`. This may be useful for
+# supplementary build information, like distro-specific package versions.
+#
+# The Rust compiler will differentiate between versions of itself, including
+# based on this string, which means that if you wish to be compatible with
+# upstream Rust you need to set this to "". However, note that if you set this to "" but
+# are not actually compatible -- for example if you've backported patches that change
+# behavior -- this may lead to miscompilations or other bugs.
+#description = ""
+
 # Build triple for the pre-compiled snapshot compiler. If `rustc` is set, this must match its host
 # triple (see `rustc --version --verbose`; cross-compiling the rust build system itself is NOT
 # supported). If `rustc` is unset, this must be a platform with pre-compiled host tools
@@ -615,17 +626,6 @@
 # If using tarball sources, default value is "auto-detect", otherwise, it's "dev".
 #channel = if "is a tarball source" { "auto-detect" } else { "dev" }
 
-# A descriptive string to be appended to `rustc --version` output, which is
-# also used in places like debuginfo `DW_AT_producer`. This may be useful for
-# supplementary build information, like distro-specific package versions.
-#
-# The Rust compiler will differentiate between versions of itself, including
-# based on this string, which means that if you wish to be compatible with
-# upstream Rust you need to set this to "". However, note that if you are not
-# actually compatible -- for example if you've backported patches that change
-# behavior -- this may lead to miscompilations or other bugs.
-#description = ""
-
 # The root location of the musl installation directory. The library directory
 # will also need to contain libunwind.a for an unwinding implementation. Note
 # that this option only makes sense for musl targets that produce statically
diff --git a/library/Cargo.lock b/library/Cargo.lock
index de9685742f5..efb6b83a093 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.148"
+version = "0.1.150"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26137996631d90d2727b905b480fdcf8c4479fdbce7afd7f8e3796d689b33cc2"
+checksum = "5c42734e0ccf0d9f953165770593a75306f0b24dda1aa03f115c70748726dbca"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -151,9 +151,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.169"
+version = "0.2.170"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
 dependencies = [
  "rustc-std-workspace-core",
 ]
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 9e80f3579e8..9cf9e98e89e 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -12,7 +12,7 @@ edition = "2021"
 
 [dependencies]
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index e686a02f29b..3bfdc68dcda 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -264,8 +264,14 @@ unsafe impl Allocator for Global {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
         if layout.size() != 0 {
-            // SAFETY: `layout` is non-zero in size,
-            // other conditions must be upheld by the caller
+            // SAFETY:
+            // * We have checked that `layout` is non-zero in size.
+            // * The caller is obligated to provide a layout that "fits", and in this case,
+            //   "fit" always means a layout that is equal to the original, because our
+            //   `allocate()`, `grow()`, and `shrink()` implementations never returns a larger
+            //   allocation than requested.
+            // * Other conditions must be upheld by the caller, as per `Allocator::deallocate()`'s
+            //   safety documentation.
             unsafe { dealloc(ptr.as_ptr(), layout) }
         }
     }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index c3f5806e1aa..9b19ab74edf 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -937,8 +937,6 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(box_uninit_write)]
-    ///
     /// let big_box = Box::<[usize; 1024]>::new_uninit();
     ///
     /// let mut array = [0; 1024];
@@ -954,7 +952,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
     ///     assert_eq!(*x, i);
     /// }
     /// ```
-    #[unstable(feature = "box_uninit_write", issue = "129397")]
+    #[stable(feature = "box_uninit_write", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub fn write(mut boxed: Self, value: T) -> Box<T, A> {
         unsafe {
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 2e9dd985715..cb93100f56c 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -102,7 +102,6 @@
 #![feature(assert_matches)]
 #![feature(async_fn_traits)]
 #![feature(async_iterator)]
-#![feature(box_uninit_write)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
 #![feature(char_max_len)]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index f10ef1fca13..fc4b93ccf8c 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1134,7 +1134,6 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// #![feature(string_extend_from_within)]
     /// let mut string = String::from("abcde");
     ///
     /// string.extend_from_within(2..);
@@ -1147,7 +1146,7 @@ impl String {
     /// assert_eq!(string, "abcdecdeabecde");
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[unstable(feature = "string_extend_from_within", issue = "103806")]
+    #[stable(feature = "string_extend_from_within", since = "CURRENT_RUSTC_VERSION")]
     pub fn extend_from_within<R>(&mut self, src: R)
     where
         R: RangeBounds<usize>,
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 764e7fff33e..3f60bb067d6 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -1693,49 +1693,41 @@ impl<'a> Formatter<'a> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pad(&mut self, s: &str) -> Result {
-        // Make sure there's a fast path up front
+        // Make sure there's a fast path up front.
         if self.options.width.is_none() && self.options.precision.is_none() {
             return self.buf.write_str(s);
         }
-        // The `precision` field can be interpreted as a `max-width` for the
+
+        // The `precision` field can be interpreted as a maximum width for the
         // string being formatted.
-        let s = if let Some(max) = self.options.precision {
-            // If our string is longer that the precision, then we must have
-            // truncation. However other flags like `fill`, `width` and `align`
-            // must act as always.
-            if let Some((i, _)) = s.char_indices().nth(max) {
-                // LLVM here can't prove that `..i` won't panic `&s[..i]`, but
-                // we know that it can't panic. Use `get` + `unwrap_or` to avoid
-                // `unsafe` and otherwise don't emit any panic-related code
-                // here.
-                s.get(..i).unwrap_or(s)
-            } else {
-                &s
-            }
+        let (s, char_count) = if let Some(max_char_count) = self.options.precision {
+            let mut iter = s.char_indices();
+            let remaining = match iter.advance_by(max_char_count) {
+                Ok(()) => 0,
+                Err(remaining) => remaining.get(),
+            };
+            // SAFETY: The offset of `.char_indices()` is guaranteed to be
+            // in-bounds and between character boundaries.
+            let truncated = unsafe { s.get_unchecked(..iter.offset()) };
+            (truncated, max_char_count - remaining)
         } else {
-            &s
+            // Use the optimized char counting algorithm for the full string.
+            (s, s.chars().count())
         };
-        // The `width` field is more of a `min-width` parameter at this point.
-        match self.options.width {
-            // If we're under the maximum length, and there's no minimum length
-            // requirements, then we can just emit the string
-            None => self.buf.write_str(s),
-            Some(width) => {
-                let chars_count = s.chars().count();
-                // If we're under the maximum width, check if we're over the minimum
-                // width, if so it's as easy as just emitting the string.
-                if chars_count >= width {
-                    self.buf.write_str(s)
-                }
-                // If we're under both the maximum and the minimum width, then fill
-                // up the minimum width with the specified string + some alignment.
-                else {
-                    let align = Alignment::Left;
-                    let post_padding = self.padding(width - chars_count, align)?;
-                    self.buf.write_str(s)?;
-                    post_padding.write(self)
-                }
-            }
+
+        // The `width` field is more of a minimum width parameter at this point.
+        if let Some(width) = self.options.width
+            && char_count < width
+        {
+            // If we're under the minimum width, then fill up the minimum width
+            // with the specified string + some alignment.
+            let post_padding = self.padding(width - char_count, Alignment::Left)?;
+            self.buf.write_str(s)?;
+            post_padding.write(self)
+        } else {
+            // If we're over the minimum width or there is no minimum width, we
+            // can just emit the string.
+            self.buf.write_str(s)
         }
     }
 
diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs
index 23334e6575d..235f8a3bb79 100644
--- a/library/core/src/marker/variance.rs
+++ b/library/core/src/marker/variance.rs
@@ -136,6 +136,8 @@ phantom_lifetime! {
     /// For all `'a`, the following are guaranteed:
     /// * `size_of::<PhantomCovariantLifetime<'a>>() == 0`
     /// * `align_of::<PhantomCovariantLifetime<'a>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>);
     /// Zero-sized type used to mark a lifetime as contravariant.
     ///
@@ -149,6 +151,8 @@ phantom_lifetime! {
     /// For all `'a`, the following are guaranteed:
     /// * `size_of::<PhantomContravariantLifetime<'a>>() == 0`
     /// * `align_of::<PhantomContravariantLifetime<'a>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>);
     /// Zero-sized type used to mark a lifetime as invariant.
     ///
@@ -162,6 +166,8 @@ phantom_lifetime! {
     /// For all `'a`, the following are guaranteed:
     /// * `size_of::<PhantomInvariantLifetime<'a>>() == 0`
     /// * `align_of::<PhantomInvariantLifetime<'a>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>);
 }
 
@@ -179,6 +185,8 @@ phantom_type! {
     /// For all `T`, the following are guaranteed:
     /// * `size_of::<PhantomCovariant<T>>() == 0`
     /// * `align_of::<PhantomCovariant<T>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomCovariant<T>(PhantomData<fn() -> T>);
     /// Zero-sized type used to mark a type parameter as contravariant.
     ///
@@ -193,6 +201,8 @@ phantom_type! {
     /// For all `T`, the following are guaranteed:
     /// * `size_of::<PhantomContravariant<T>>() == 0`
     /// * `align_of::<PhantomContravariant<T>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomContravariant<T>(PhantomData<fn(T)>);
     /// Zero-sized type used to mark a type parameter as invariant.
     ///
@@ -206,6 +216,8 @@ phantom_type! {
     /// For all `T`, the following are guaranteed:
     /// * `size_of::<PhantomInvariant<T>>() == 0`
     /// * `align_of::<PhantomInvariant<T>>() == 1`
+    #[rustc_pub_transparent]
+    #[repr(transparent)]
     pub struct PhantomInvariant<T>(PhantomData<fn(T) -> T>);
 }
 
diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs
index 4dadf406ae8..a140a311c45 100644
--- a/library/core/src/num/dec2flt/common.rs
+++ b/library/core/src/num/dec2flt/common.rs
@@ -8,12 +8,12 @@ pub(crate) trait ByteSlice {
     /// Writes a 64-bit integer as 8 bytes in little-endian order.
     fn write_u64(&mut self, value: u64);
 
-    /// Calculate the offset of a slice from another.
+    /// Calculate the difference in length between two slices.
     fn offset_from(&self, other: &Self) -> isize;
 
     /// Iteratively parse and consume digits from bytes.
-    /// Returns the same bytes with consumed digits being
-    /// elided.
+    ///
+    /// Returns the same bytes with consumed digits being elided. Breaks on invalid digits.
     fn parse_digits(&self, func: impl FnMut(u8)) -> &Self;
 }
 
@@ -39,11 +39,11 @@ impl ByteSlice for [u8] {
     fn parse_digits(&self, mut func: impl FnMut(u8)) -> &Self {
         let mut s = self;
 
-        while let Some((c, s_next)) = s.split_first() {
+        while let Some((c, rest)) = s.split_first() {
             let c = c.wrapping_sub(b'0');
             if c < 10 {
                 func(c);
-                s = s_next;
+                s = rest;
             } else {
                 break;
             }
@@ -53,7 +53,9 @@ impl ByteSlice for [u8] {
     }
 }
 
-/// Determine if 8 bytes are all decimal digits.
+/// Determine if all characters in an 8-byte byte string (represented as a `u64`) are all decimal
+/// digits.
+///
 /// This does not care about the order in which the bytes were loaded.
 pub(crate) fn is_8digits(v: u64) -> bool {
     let a = v.wrapping_add(0x4646_4646_4646_4646);
@@ -61,19 +63,20 @@ pub(crate) fn is_8digits(v: u64) -> bool {
     (a | b) & 0x8080_8080_8080_8080 == 0
 }
 
-/// A custom 64-bit floating point type, representing `f * 2^e`.
-/// e is biased, so it be directly shifted into the exponent bits.
+/// A custom 64-bit floating point type, representing `m * 2^p`.
+/// p is biased, so it be directly shifted into the exponent bits.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
 pub struct BiasedFp {
     /// The significant digits.
-    pub f: u64,
+    pub m: u64,
     /// The biased, binary exponent.
-    pub e: i32,
+    pub p_biased: i32,
 }
 
 impl BiasedFp {
+    /// Represent `0 ^ p`
     #[inline]
-    pub const fn zero_pow2(e: i32) -> Self {
-        Self { f: 0, e }
+    pub const fn zero_pow2(p_biased: i32) -> Self {
+        Self { m: 0, p_biased }
     }
 }
diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs
index b37724ba62d..db7176c1243 100644
--- a/library/core/src/num/dec2flt/decimal.rs
+++ b/library/core/src/num/dec2flt/decimal.rs
@@ -1,358 +1,87 @@
-//! Arbitrary-precision decimal class for fallback algorithms.
-//!
-//! This is only used if the fast-path (native floats) and
-//! the Eisel-Lemire algorithm are unable to unambiguously
-//! determine the float.
-//!
-//! The technique used is "Simple Decimal Conversion", developed
-//! by Nigel Tao and Ken Thompson. A detailed description of the
-//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
-//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
-
-use crate::num::dec2flt::common::{ByteSlice, is_8digits};
-
-#[derive(Clone)]
-pub(super) struct Decimal {
-    /// The number of significant digits in the decimal.
-    pub num_digits: usize,
-    /// The offset of the decimal point in the significant digits.
-    pub decimal_point: i32,
-    /// If the number of significant digits stored in the decimal is truncated.
-    pub truncated: bool,
-    /// Buffer of the raw digits, in the range [0, 9].
-    pub digits: [u8; Self::MAX_DIGITS],
+//! Representation of a float as the significant digits and exponent.
+
+use crate::num::dec2flt::float::RawFloat;
+use crate::num::dec2flt::fpu::set_precision;
+
+const INT_POW10: [u64; 16] = [
+    1,
+    10,
+    100,
+    1000,
+    10000,
+    100000,
+    1000000,
+    10000000,
+    100000000,
+    1000000000,
+    10000000000,
+    100000000000,
+    1000000000000,
+    10000000000000,
+    100000000000000,
+    1000000000000000,
+];
+
+/// A floating point number with up to 64 bits of mantissa and an `i64` exponent.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
+pub struct Decimal {
+    pub exponent: i64,
+    pub mantissa: u64,
+    pub negative: bool,
+    pub many_digits: bool,
 }
 
-impl Default for Decimal {
-    fn default() -> Self {
-        Self { num_digits: 0, decimal_point: 0, truncated: false, digits: [0; Self::MAX_DIGITS] }
+impl Decimal {
+    /// Detect if the float can be accurately reconstructed from native floats.
+    #[inline]
+    fn can_use_fast_path<F: RawFloat>(&self) -> bool {
+        F::MIN_EXPONENT_FAST_PATH <= self.exponent
+            && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH
+            && self.mantissa <= F::MAX_MANTISSA_FAST_PATH
+            && !self.many_digits
     }
-}
 
-impl Decimal {
-    /// The maximum number of digits required to unambiguously round a float.
-    ///
-    /// For a double-precision IEEE 754 float, this required 767 digits,
-    /// so we store the max digits + 1.
-    ///
-    /// We can exactly represent a float in radix `b` from radix 2 if
-    /// `b` is divisible by 2. This function calculates the exact number of
-    /// digits required to exactly represent that float.
-    ///
-    /// According to the "Handbook of Floating Point Arithmetic",
-    /// for IEEE754, with emin being the min exponent, p2 being the
-    /// precision, and b being the radix, the number of digits follows as:
+    /// Try turning the decimal into an exact float representation, using machine-sized integers
+    /// and floats.
     ///
-    /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
+    /// This is extracted into a separate function so that it can be attempted before constructing
+    /// a Decimal. This only works if both the mantissa and the exponent
+    /// can be exactly represented as a machine float, since IEE-754 guarantees
+    /// no rounding will occur.
     ///
-    /// For f32, this follows as:
-    ///     emin = -126
-    ///     p2 = 24
-    ///
-    /// For f64, this follows as:
-    ///     emin = -1022
-    ///     p2 = 53
-    ///
-    /// In Python:
-    ///     `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))`
-    pub(super) const MAX_DIGITS: usize = 768;
-    /// The max digits that can be exactly represented in a 64-bit integer.
-    pub(super) const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19;
-    pub(super) const DECIMAL_POINT_RANGE: i32 = 2047;
-
-    /// Append a digit to the buffer.
-    pub(super) fn try_add_digit(&mut self, digit: u8) {
-        if self.num_digits < Self::MAX_DIGITS {
-            self.digits[self.num_digits] = digit;
-        }
-        self.num_digits += 1;
-    }
-
-    /// Trim trailing zeros from the buffer.
-    pub(super) fn trim(&mut self) {
-        // All of the following calls to `Decimal::trim` can't panic because:
-        //
-        //  1. `parse_decimal` sets `num_digits` to a max of `Decimal::MAX_DIGITS`.
-        //  2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`.
-        //  3. `left_shift` `num_digits` to a max of `Decimal::MAX_DIGITS`.
-        //
-        // Trim is only called in `right_shift` and `left_shift`.
-        debug_assert!(self.num_digits <= Self::MAX_DIGITS);
-        while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 {
-            self.num_digits -= 1;
-        }
-    }
-
-    pub(super) fn round(&self) -> u64 {
-        if self.num_digits == 0 || self.decimal_point < 0 {
-            return 0;
-        } else if self.decimal_point > 18 {
-            return 0xFFFF_FFFF_FFFF_FFFF_u64;
-        }
-        let dp = self.decimal_point as usize;
-        let mut n = 0_u64;
-        for i in 0..dp {
-            n *= 10;
-            if i < self.num_digits {
-                n += self.digits[i] as u64;
-            }
-        }
-        let mut round_up = false;
-        if dp < self.num_digits {
-            round_up = self.digits[dp] >= 5;
-            if self.digits[dp] == 5 && dp + 1 == self.num_digits {
-                round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0))
-            }
-        }
-        if round_up {
-            n += 1;
-        }
-        n
-    }
-
-    /// Computes decimal * 2^shift.
-    pub(super) fn left_shift(&mut self, shift: usize) {
-        if self.num_digits == 0 {
-            return;
-        }
-        let num_new_digits = number_of_digits_decimal_left_shift(self, shift);
-        let mut read_index = self.num_digits;
-        let mut write_index = self.num_digits + num_new_digits;
-        let mut n = 0_u64;
-        while read_index != 0 {
-            read_index -= 1;
-            write_index -= 1;
-            n += (self.digits[read_index] as u64) << shift;
-            let quotient = n / 10;
-            let remainder = n - (10 * quotient);
-            if write_index < Self::MAX_DIGITS {
-                self.digits[write_index] = remainder as u8;
-            } else if remainder > 0 {
-                self.truncated = true;
-            }
-            n = quotient;
-        }
-        while n > 0 {
-            write_index -= 1;
-            let quotient = n / 10;
-            let remainder = n - (10 * quotient);
-            if write_index < Self::MAX_DIGITS {
-                self.digits[write_index] = remainder as u8;
-            } else if remainder > 0 {
-                self.truncated = true;
-            }
-            n = quotient;
-        }
-        self.num_digits += num_new_digits;
-        if self.num_digits > Self::MAX_DIGITS {
-            self.num_digits = Self::MAX_DIGITS;
-        }
-        self.decimal_point += num_new_digits as i32;
-        self.trim();
-    }
-
-    /// Computes decimal * 2^-shift.
-    pub(super) fn right_shift(&mut self, shift: usize) {
-        let mut read_index = 0;
-        let mut write_index = 0;
-        let mut n = 0_u64;
-        while (n >> shift) == 0 {
-            if read_index < self.num_digits {
-                n = (10 * n) + self.digits[read_index] as u64;
-                read_index += 1;
-            } else if n == 0 {
-                return;
+    /// There is an exception: disguised fast-path cases, where we can shift
+    /// powers-of-10 from the exponent to the significant digits.
+    pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
+        // Here we need to work around <https://github.com/rust-lang/rust/issues/114479>.
+        // The fast path crucially depends on arithmetic being rounded to the correct number of bits
+        // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
+        // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
+        // The `set_precision` function takes care of setting the precision on architectures which
+        // require setting it by changing the global state (like the control word of the x87 FPU).
+        let _cw = set_precision::<F>();
+
+        if !self.can_use_fast_path::<F>() {
+            return None;
+        }
+
+        let value = if self.exponent <= F::MAX_EXPONENT_FAST_PATH {
+            // normal fast path
+            let value = F::from_u64(self.mantissa);
+            if self.exponent < 0 {
+                value / F::pow10_fast_path((-self.exponent) as _)
             } else {
-                while (n >> shift) == 0 {
-                    n *= 10;
-                    read_index += 1;
-                }
-                break;
-            }
-        }
-        self.decimal_point -= read_index as i32 - 1;
-        if self.decimal_point < -Self::DECIMAL_POINT_RANGE {
-            // `self = Self::Default()`, but without the overhead of clearing `digits`.
-            self.num_digits = 0;
-            self.decimal_point = 0;
-            self.truncated = false;
-            return;
-        }
-        let mask = (1_u64 << shift) - 1;
-        while read_index < self.num_digits {
-            let new_digit = (n >> shift) as u8;
-            n = (10 * (n & mask)) + self.digits[read_index] as u64;
-            read_index += 1;
-            self.digits[write_index] = new_digit;
-            write_index += 1;
-        }
-        while n > 0 {
-            let new_digit = (n >> shift) as u8;
-            n = 10 * (n & mask);
-            if write_index < Self::MAX_DIGITS {
-                self.digits[write_index] = new_digit;
-                write_index += 1;
-            } else if new_digit > 0 {
-                self.truncated = true;
-            }
-        }
-        self.num_digits = write_index;
-        self.trim();
-    }
-}
-
-/// Parse a big integer representation of the float as a decimal.
-pub(super) fn parse_decimal(mut s: &[u8]) -> Decimal {
-    let mut d = Decimal::default();
-    let start = s;
-
-    while let Some((&b'0', s_next)) = s.split_first() {
-        s = s_next;
-    }
-
-    s = s.parse_digits(|digit| d.try_add_digit(digit));
-
-    if let Some((b'.', s_next)) = s.split_first() {
-        s = s_next;
-        let first = s;
-        // Skip leading zeros.
-        if d.num_digits == 0 {
-            while let Some((&b'0', s_next)) = s.split_first() {
-                s = s_next;
-            }
-        }
-        while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS {
-            let v = s.read_u64();
-            if !is_8digits(v) {
-                break;
+                value * F::pow10_fast_path(self.exponent as _)
             }
-            d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030);
-            d.num_digits += 8;
-            s = &s[8..];
-        }
-        s = s.parse_digits(|digit| d.try_add_digit(digit));
-        d.decimal_point = s.len() as i32 - first.len() as i32;
-    }
-    if d.num_digits != 0 {
-        // Ignore the trailing zeros if there are any
-        let mut n_trailing_zeros = 0;
-        for &c in start[..(start.len() - s.len())].iter().rev() {
-            if c == b'0' {
-                n_trailing_zeros += 1;
-            } else if c != b'.' {
-                break;
-            }
-        }
-        d.decimal_point += n_trailing_zeros as i32;
-        d.num_digits -= n_trailing_zeros;
-        d.decimal_point += d.num_digits as i32;
-        if d.num_digits > Decimal::MAX_DIGITS {
-            d.truncated = true;
-            d.num_digits = Decimal::MAX_DIGITS;
-        }
-    }
-    if let Some((&ch, s_next)) = s.split_first() {
-        if ch == b'e' || ch == b'E' {
-            s = s_next;
-            let mut neg_exp = false;
-            if let Some((&ch, s_next)) = s.split_first() {
-                neg_exp = ch == b'-';
-                if ch == b'-' || ch == b'+' {
-                    s = s_next;
-                }
+        } else {
+            // disguised fast path
+            let shift = self.exponent - F::MAX_EXPONENT_FAST_PATH;
+            let mantissa = self.mantissa.checked_mul(INT_POW10[shift as usize])?;
+            if mantissa > F::MAX_MANTISSA_FAST_PATH {
+                return None;
             }
-            let mut exp_num = 0_i32;
-
-            s.parse_digits(|digit| {
-                if exp_num < 0x10000 {
-                    exp_num = 10 * exp_num + digit as i32;
-                }
-            });
+            F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _)
+        };
 
-            d.decimal_point += if neg_exp { -exp_num } else { exp_num };
-        }
-    }
-    for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW {
-        d.digits[i] = 0;
-    }
-    d
-}
-
-fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize {
-    #[rustfmt::skip]
-    const TABLE: [u16; 65] = [
-        0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024,
-        0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C,
-        0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169,
-        0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B,
-        0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02,
-        0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C,
-    ];
-    #[rustfmt::skip]
-    const TABLE_POW5: [u8; 0x051C] = [
-        5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1,
-        9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5,
-        1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2,
-        5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6,
-        9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1,
-        6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9,
-        1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6,
-        4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1,
-        4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2,
-        3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6,
-        2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5,
-        4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2,
-        5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5,
-        3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4,
-        6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6,
-        1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0,
-        6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3,
-        6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8,
-        9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4,
-        7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5,
-        0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5,
-        4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7,
-        7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
-        8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0,
-        9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0,
-        8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1,
-        0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2,
-        5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8,
-        9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0,
-        6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3,
-        8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2,
-        6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4,
-        9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1,
-        1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8,
-        2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5,
-        8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1,
-        3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8,
-        7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0,
-        6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2,
-        5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1,
-        8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2,
-        3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3,
-        8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2,
-        2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
-    ];
-
-    shift &= 63;
-    let x_a = TABLE[shift];
-    let x_b = TABLE[shift + 1];
-    let num_new_digits = (x_a >> 11) as _;
-    let pow5_a = (0x7FF & x_a) as usize;
-    let pow5_b = (0x7FF & x_b) as usize;
-    let pow5 = &TABLE_POW5[pow5_a..];
-    for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) {
-        if i >= d.num_digits {
-            return num_new_digits - 1;
-        } else if d.digits[i] == p5 {
-            continue;
-        } else if d.digits[i] < p5 {
-            return num_new_digits - 1;
-        } else {
-            return num_new_digits;
-        }
+        if self.negative { Some(-value) } else { Some(value) }
     }
-    num_new_digits
 }
diff --git a/library/core/src/num/dec2flt/decimal_seq.rs b/library/core/src/num/dec2flt/decimal_seq.rs
new file mode 100644
index 00000000000..de22280c001
--- /dev/null
+++ b/library/core/src/num/dec2flt/decimal_seq.rs
@@ -0,0 +1,379 @@
+//! Arbitrary-precision decimal type used by fallback algorithms.
+//!
+//! This is only used if the fast-path (native floats) and
+//! the Eisel-Lemire algorithm are unable to unambiguously
+//! determine the float.
+//!
+//! The technique used is "Simple Decimal Conversion", developed
+//! by Nigel Tao and Ken Thompson. A detailed description of the
+//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
+//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
+
+use crate::num::dec2flt::common::{ByteSlice, is_8digits};
+
+/// A decimal floating-point number, represented as a sequence of decimal digits.
+#[derive(Clone, Debug, PartialEq)]
+pub struct DecimalSeq {
+    /// The number of significant digits in the decimal.
+    pub num_digits: usize,
+    /// The offset of the decimal point in the significant digits.
+    pub decimal_point: i32,
+    /// If the number of significant digits stored in the decimal is truncated.
+    pub truncated: bool,
+    /// Buffer of the raw digits, in the range [0, 9].
+    pub digits: [u8; Self::MAX_DIGITS],
+}
+
+impl Default for DecimalSeq {
+    fn default() -> Self {
+        Self { num_digits: 0, decimal_point: 0, truncated: false, digits: [0; Self::MAX_DIGITS] }
+    }
+}
+
+impl DecimalSeq {
+    /// The maximum number of digits required to unambiguously round up to a 64-bit float.
+    ///
+    /// For an IEEE 754 binary64 float, this required 767 digits. So we store the max digits + 1.
+    ///
+    /// We can exactly represent a float in radix `b` from radix 2 if
+    /// `b` is divisible by 2. This function calculates the exact number of
+    /// digits required to exactly represent that float.
+    ///
+    /// According to the "Handbook of Floating Point Arithmetic",
+    /// for IEEE754, with `emin` being the min exponent, `p2` being the
+    /// precision, and `b` being the radix, the number of digits follows as:
+    ///
+    /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
+    ///
+    /// For f32, this follows as:
+    ///     emin = -126
+    ///     p2 = 24
+    ///
+    /// For f64, this follows as:
+    ///     emin = -1022
+    ///     p2 = 53
+    ///
+    /// In Python:
+    ///     `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))`
+    pub const MAX_DIGITS: usize = 768;
+
+    /// The max decimal digits that can be exactly represented in a 64-bit integer.
+    pub(super) const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19;
+    pub(super) const DECIMAL_POINT_RANGE: i32 = 2047;
+
+    /// Append a digit to the buffer if it fits.
+    // FIXME(tgross35): it may be better for this to return an option
+    // FIXME(tgross35): incrementing the digit counter even if we don't push anything
+    // seems incorrect.
+    pub(super) fn try_add_digit(&mut self, digit: u8) {
+        if self.num_digits < Self::MAX_DIGITS {
+            self.digits[self.num_digits] = digit;
+        }
+        self.num_digits += 1;
+    }
+
+    /// Trim trailing zeros from the buffer.
+    // FIXME(tgross35): this could be `.rev().position()` if perf is okay
+    pub fn trim(&mut self) {
+        // All of the following calls to `DecimalSeq::trim` can't panic because:
+        //
+        //  1. `parse_decimal` sets `num_digits` to a max of `DecimalSeq::MAX_DIGITS`.
+        //  2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`.
+        //  3. `left_shift` `num_digits` to a max of `DecimalSeq::MAX_DIGITS`.
+        //
+        // Trim is only called in `right_shift` and `left_shift`.
+        debug_assert!(self.num_digits <= Self::MAX_DIGITS);
+        while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 {
+            self.num_digits -= 1;
+        }
+    }
+
+    pub(super) fn round(&self) -> u64 {
+        if self.num_digits == 0 || self.decimal_point < 0 {
+            return 0;
+        } else if self.decimal_point >= Self::MAX_DIGITS_WITHOUT_OVERFLOW as i32 {
+            return 0xFFFF_FFFF_FFFF_FFFF_u64;
+        }
+
+        let dp = self.decimal_point as usize;
+        let mut n = 0_u64;
+
+        for i in 0..dp {
+            n *= 10;
+            if i < self.num_digits {
+                n += self.digits[i] as u64;
+            }
+        }
+
+        let mut round_up = false;
+
+        if dp < self.num_digits {
+            round_up = self.digits[dp] >= 5;
+            if self.digits[dp] == 5 && dp + 1 == self.num_digits {
+                round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0))
+            }
+        }
+
+        if round_up {
+            n += 1;
+        }
+        n
+    }
+
+    /// Computes decimal * 2^shift.
+    pub(super) fn left_shift(&mut self, shift: usize) {
+        if self.num_digits == 0 {
+            return;
+        }
+        let num_new_digits = number_of_digits_decimal_left_shift(self, shift);
+        let mut read_index = self.num_digits;
+        let mut write_index = self.num_digits + num_new_digits;
+        let mut n = 0_u64;
+
+        while read_index != 0 {
+            read_index -= 1;
+            write_index -= 1;
+            n += (self.digits[read_index] as u64) << shift;
+            let quotient = n / 10;
+            let remainder = n - (10 * quotient);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = remainder as u8;
+            } else if remainder > 0 {
+                self.truncated = true;
+            }
+            n = quotient;
+        }
+
+        while n > 0 {
+            write_index -= 1;
+            let quotient = n / 10;
+            let remainder = n - (10 * quotient);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = remainder as u8;
+            } else if remainder > 0 {
+                self.truncated = true;
+            }
+            n = quotient;
+        }
+
+        self.num_digits += num_new_digits;
+
+        if self.num_digits > Self::MAX_DIGITS {
+            self.num_digits = Self::MAX_DIGITS;
+        }
+
+        self.decimal_point += num_new_digits as i32;
+        self.trim();
+    }
+
+    /// Computes decimal * 2^-shift.
+    pub(super) fn right_shift(&mut self, shift: usize) {
+        let mut read_index = 0;
+        let mut write_index = 0;
+        let mut n = 0_u64;
+        while (n >> shift) == 0 {
+            if read_index < self.num_digits {
+                n = (10 * n) + self.digits[read_index] as u64;
+                read_index += 1;
+            } else if n == 0 {
+                return;
+            } else {
+                while (n >> shift) == 0 {
+                    n *= 10;
+                    read_index += 1;
+                }
+                break;
+            }
+        }
+        self.decimal_point -= read_index as i32 - 1;
+        if self.decimal_point < -Self::DECIMAL_POINT_RANGE {
+            // `self = Self::Default()`, but without the overhead of clearing `digits`.
+            self.num_digits = 0;
+            self.decimal_point = 0;
+            self.truncated = false;
+            return;
+        }
+        let mask = (1_u64 << shift) - 1;
+        while read_index < self.num_digits {
+            let new_digit = (n >> shift) as u8;
+            n = (10 * (n & mask)) + self.digits[read_index] as u64;
+            read_index += 1;
+            self.digits[write_index] = new_digit;
+            write_index += 1;
+        }
+        while n > 0 {
+            let new_digit = (n >> shift) as u8;
+            n = 10 * (n & mask);
+            if write_index < Self::MAX_DIGITS {
+                self.digits[write_index] = new_digit;
+                write_index += 1;
+            } else if new_digit > 0 {
+                self.truncated = true;
+            }
+        }
+        self.num_digits = write_index;
+        self.trim();
+    }
+}
+
+/// Parse a big integer representation of the float as a decimal.
+pub fn parse_decimal_seq(mut s: &[u8]) -> DecimalSeq {
+    let mut d = DecimalSeq::default();
+    let start = s;
+
+    while let Some((&b'0', s_next)) = s.split_first() {
+        s = s_next;
+    }
+
+    s = s.parse_digits(|digit| d.try_add_digit(digit));
+
+    if let Some((b'.', s_next)) = s.split_first() {
+        s = s_next;
+        let first = s;
+        // Skip leading zeros.
+        if d.num_digits == 0 {
+            while let Some((&b'0', s_next)) = s.split_first() {
+                s = s_next;
+            }
+        }
+        while s.len() >= 8 && d.num_digits + 8 < DecimalSeq::MAX_DIGITS {
+            let v = s.read_u64();
+            if !is_8digits(v) {
+                break;
+            }
+            d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030);
+            d.num_digits += 8;
+            s = &s[8..];
+        }
+        s = s.parse_digits(|digit| d.try_add_digit(digit));
+        d.decimal_point = s.len() as i32 - first.len() as i32;
+    }
+
+    if d.num_digits != 0 {
+        // Ignore the trailing zeros if there are any
+        let mut n_trailing_zeros = 0;
+        for &c in start[..(start.len() - s.len())].iter().rev() {
+            if c == b'0' {
+                n_trailing_zeros += 1;
+            } else if c != b'.' {
+                break;
+            }
+        }
+        d.decimal_point += n_trailing_zeros as i32;
+        d.num_digits -= n_trailing_zeros;
+        d.decimal_point += d.num_digits as i32;
+        if d.num_digits > DecimalSeq::MAX_DIGITS {
+            d.truncated = true;
+            d.num_digits = DecimalSeq::MAX_DIGITS;
+        }
+    }
+
+    if let Some((&ch, s_next)) = s.split_first() {
+        if ch == b'e' || ch == b'E' {
+            s = s_next;
+            let mut neg_exp = false;
+            if let Some((&ch, s_next)) = s.split_first() {
+                neg_exp = ch == b'-';
+                if ch == b'-' || ch == b'+' {
+                    s = s_next;
+                }
+            }
+            let mut exp_num = 0_i32;
+
+            s.parse_digits(|digit| {
+                if exp_num < 0x10000 {
+                    exp_num = 10 * exp_num + digit as i32;
+                }
+            });
+
+            d.decimal_point += if neg_exp { -exp_num } else { exp_num };
+        }
+    }
+
+    for i in d.num_digits..DecimalSeq::MAX_DIGITS_WITHOUT_OVERFLOW {
+        d.digits[i] = 0;
+    }
+
+    d
+}
+
+fn number_of_digits_decimal_left_shift(d: &DecimalSeq, mut shift: usize) -> usize {
+    #[rustfmt::skip]
+    const TABLE: [u16; 65] = [
+        0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024,
+        0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C,
+        0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169,
+        0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B,
+        0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02,
+        0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C,
+    ];
+    #[rustfmt::skip]
+    const TABLE_POW5: [u8; 0x051C] = [
+        5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1,
+        9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5,
+        1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2,
+        5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6,
+        9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1,
+        6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9,
+        1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6,
+        4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1,
+        4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2,
+        3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6,
+        2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5,
+        4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2,
+        5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5,
+        3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4,
+        6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6,
+        1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0,
+        6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3,
+        6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8,
+        9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4,
+        7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5,
+        0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5,
+        4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7,
+        7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
+        8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0,
+        9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0,
+        8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1,
+        0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2,
+        5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8,
+        9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0,
+        6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3,
+        8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2,
+        6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4,
+        9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1,
+        1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8,
+        2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5,
+        8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1,
+        3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8,
+        7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0,
+        6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2,
+        5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1,
+        8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2,
+        3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3,
+        8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2,
+        2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
+    ];
+
+    shift &= 63;
+    let x_a = TABLE[shift];
+    let x_b = TABLE[shift + 1];
+    let num_new_digits = (x_a >> 11) as _;
+    let pow5_a = (0x7FF & x_a) as usize;
+    let pow5_b = (0x7FF & x_b) as usize;
+    let pow5 = &TABLE_POW5[pow5_a..];
+
+    for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) {
+        if i >= d.num_digits {
+            return num_new_digits - 1;
+        } else if d.digits[i] == p5 {
+            continue;
+        } else if d.digits[i] < p5 {
+            return num_new_digits - 1;
+        } else {
+            return num_new_digits;
+        }
+    }
+
+    num_new_digits
+}
diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs
index da57aa9a546..b8a28a67569 100644
--- a/library/core/src/num/dec2flt/float.rs
+++ b/library/core/src/num/dec2flt/float.rs
@@ -1,14 +1,57 @@
 //! Helper trait for generic float types.
 
+use core::f64;
+
 use crate::fmt::{Debug, LowerExp};
 use crate::num::FpCategory;
-use crate::ops::{Add, Div, Mul, Neg};
+use crate::ops::{self, Add, Div, Mul, Neg};
+
+/// Lossy `as` casting between two types.
+pub trait CastInto<T: Copy>: Copy {
+    fn cast(self) -> T;
+}
+
+/// Collection of traits that allow us to be generic over integer size.
+pub trait Integer:
+    Sized
+    + Clone
+    + Copy
+    + Debug
+    + ops::Shr<u32, Output = Self>
+    + ops::Shl<u32, Output = Self>
+    + ops::BitAnd<Output = Self>
+    + ops::BitOr<Output = Self>
+    + PartialEq
+    + CastInto<i16>
+{
+    const ZERO: Self;
+    const ONE: Self;
+}
+
+macro_rules! int {
+    ($($ty:ty),+) => {
+        $(
+            impl CastInto<i16> for $ty {
+                fn cast(self) -> i16 {
+                    self as i16
+                }
+            }
+
+            impl Integer for $ty {
+                const ZERO: Self = 0;
+                const ONE: Self = 1;
+            }
+        )+
+    }
+}
+
+int!(u32, u64);
 
-/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`.
+/// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
 ///
 /// See the parent module's doc comment for why this is necessary.
 ///
-/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
+/// Should **never ever** be implemented for other types or be used outside the `dec2flt` module.
 #[doc(hidden)]
 pub trait RawFloat:
     Sized
@@ -24,62 +67,107 @@ pub trait RawFloat:
     + Copy
     + Debug
 {
+    /// The unsigned integer with the same size as the float
+    type Int: Integer + Into<u64>;
+
+    /* general constants */
+
     const INFINITY: Self;
     const NEG_INFINITY: Self;
     const NAN: Self;
     const NEG_NAN: Self;
 
-    /// The number of bits in the significand, *excluding* the hidden bit.
-    const MANTISSA_EXPLICIT_BITS: usize;
-
-    // Round-to-even only happens for negative values of q
-    // when q ≥ −4 in the 64-bit case and when q ≥ −17 in
-    // the 32-bitcase.
-    //
-    // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we
-    // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have
-    // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10.
-    //
-    // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64
-    // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case)
-    // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64
-    // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11
-    // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase).
-    //
-    // Thus we have that we only need to round ties to even when
-    // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10]
-    // (in the 32-bit case). In both cases,the power of five(5^|q|)
-    // fits in a 64-bit word.
-    const MIN_EXPONENT_ROUND_TO_EVEN: i32;
-    const MAX_EXPONENT_ROUND_TO_EVEN: i32;
+    /// Bit width of the float
+    const BITS: u32;
 
-    // Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
-    const MIN_EXPONENT_FAST_PATH: i64;
+    /// The number of bits in the significand, *including* the hidden bit.
+    const SIG_TOTAL_BITS: u32;
 
-    // Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
-    const MAX_EXPONENT_FAST_PATH: i64;
+    const EXP_MASK: Self::Int;
+    const SIG_MASK: Self::Int;
 
-    // Maximum exponent that can be represented for a disguised-fast path case.
-    // This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋`
-    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64;
-
-    // Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`.
-    const MINIMUM_EXPONENT: i32;
+    /// The number of bits in the significand, *excluding* the hidden bit.
+    const SIG_BITS: u32 = Self::SIG_TOTAL_BITS - 1;
+
+    /// Number of bits in the exponent.
+    const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
+
+    /// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
+    /// representation.
+    ///
+    /// This shifted fully right, use `EXP_MASK` for the shifted value.
+    const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
+
+    /// Signed version of `EXP_SAT` since we convert a lot.
+    const INFINITE_POWER: i32 = Self::EXP_SAT as i32;
+
+    /// The exponent bias value. This is also the maximum value of the exponent.
+    const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
+
+    /// Minimum exponent value of normal values.
+    const EXP_MIN: i32 = -(Self::EXP_BIAS as i32 - 1);
+
+    /// Round-to-even only happens for negative values of q
+    /// when q ≥ −4 in the 64-bit case and when q ≥ −17 in
+    /// the 32-bitcase.
+    ///
+    /// When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we
+    /// have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have
+    /// 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10.
+    ///
+    /// When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64
+    /// so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case)
+    /// or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64
+    /// (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11
+    /// or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase).
+    ///
+    /// Thus we have that we only need to round ties to even when
+    /// we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10]
+    /// (in the 32-bit case). In both cases,the power of five(5^|q|)
+    /// fits in a 64-bit word.
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32;
 
-    // Largest exponent value `(1 << EXP_BITS) - 1`.
-    const INFINITE_POWER: i32;
+    /* limits related to Fast pathing */
+
+    /// Largest decimal exponent for a non-infinite value.
+    ///
+    /// This is the max exponent in binary converted to the max exponent in decimal. Allows fast
+    /// pathing anything larger than `10^LARGEST_POWER_OF_TEN`, which will round to infinity.
+    const LARGEST_POWER_OF_TEN: i32 = {
+        let largest_pow2 = Self::EXP_BIAS + 1;
+        pow2_to_pow10(largest_pow2 as i64) as i32
+    };
+
+    /// Smallest decimal exponent for a non-zero value. This allows for fast pathing anything
+    /// smaller than `10^SMALLEST_POWER_OF_TEN`, which will round to zero.
+    ///
+    /// The smallest power of ten is represented by `⌊log10(2^-n / (2^64 - 1))⌋`, where `n` is
+    /// the smallest power of two. The `2^64 - 1)` denomenator comes from the number of values
+    /// that are representable by the intermediate storage format. I don't actually know _why_
+    /// the storage format is relevant here.
+    ///
+    /// The values may be calculated using the formula. Unfortunately we cannot calculate them at
+    /// compile time since intermediates exceed the range of an `f64`.
+    const SMALLEST_POWER_OF_TEN: i32;
 
-    // Index (in bits) of the sign.
-    const SIGN_INDEX: usize;
+    /// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
+    // assuming FLT_EVAL_METHOD = 0
+    const MAX_EXPONENT_FAST_PATH: i64 = {
+        let log2_5 = f64::consts::LOG2_10 - 1.0;
+        (Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
+    };
 
-    // Smallest decimal exponent for a non-zero value.
-    const SMALLEST_POWER_OF_TEN: i32;
+    /// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
+    const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
 
-    // Largest decimal exponent for a non-infinite value.
-    const LARGEST_POWER_OF_TEN: i32;
+    /// Maximum exponent that can be represented for a disguised-fast path case.
+    /// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
+    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
+        Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
 
-    // Maximum mantissa for the fast-path (`1 << 53` for f64).
-    const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS;
+    /// Maximum mantissa for the fast-path (`1 << 53` for f64).
+    const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
 
     /// Converts integer into float through an as cast.
     /// This is only called in the fast-path algorithm, and therefore
@@ -96,27 +184,51 @@ pub trait RawFloat:
     /// Returns the category that this number falls into.
     fn classify(self) -> FpCategory;
 
+    /// Transmute to the integer representation
+    fn to_bits(self) -> Self::Int;
+
     /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8);
+    ///
+    /// That is, this returns `(m, p, s)` such that `s * m * 2^p` represents the original float.
+    /// For 0, the exponent will be `-(EXP_BIAS + SIG_BITS`, which is the
+    /// minimum subnormal power.
+    fn integer_decode(self) -> (u64, i16, i8) {
+        let bits = self.to_bits();
+        let sign: i8 = if bits >> (Self::BITS - 1) == Self::Int::ZERO { 1 } else { -1 };
+        let mut exponent: i16 = ((bits & Self::EXP_MASK) >> Self::SIG_BITS).cast();
+        let mantissa = if exponent == 0 {
+            (bits & Self::SIG_MASK) << 1
+        } else {
+            (bits & Self::SIG_MASK) | (Self::Int::ONE << Self::SIG_BITS)
+        };
+        // Exponent bias + mantissa shift
+        exponent -= (Self::EXP_BIAS + Self::SIG_BITS) as i16;
+        (mantissa.into(), exponent, sign)
+    }
+}
+
+/// Solve for `b` in `10^b = 2^a`
+const fn pow2_to_pow10(a: i64) -> i64 {
+    let res = (a as f64) / f64::consts::LOG2_10;
+    res as i64
 }
 
 impl RawFloat for f32 {
+    type Int = u32;
+
     const INFINITY: Self = f32::INFINITY;
     const NEG_INFINITY: Self = f32::NEG_INFINITY;
     const NAN: Self = f32::NAN;
     const NEG_NAN: Self = -f32::NAN;
 
-    const MANTISSA_EXPLICIT_BITS: usize = 23;
+    const BITS: u32 = 32;
+    const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
+    const EXP_MASK: Self::Int = Self::EXP_MASK;
+    const SIG_MASK: Self::Int = Self::MAN_MASK;
+
     const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
     const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
-    const MIN_EXPONENT_FAST_PATH: i64 = -10; // assuming FLT_EVAL_METHOD = 0
-    const MAX_EXPONENT_FAST_PATH: i64 = 10;
-    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17;
-    const MINIMUM_EXPONENT: i32 = -127;
-    const INFINITE_POWER: i32 = 0xFF;
-    const SIGN_INDEX: usize = 31;
     const SMALLEST_POWER_OF_TEN: i32 = -65;
-    const LARGEST_POWER_OF_TEN: i32 = 38;
 
     #[inline]
     fn from_u64(v: u64) -> Self {
@@ -136,16 +248,8 @@ impl RawFloat for f32 {
         TABLE[exponent & 15]
     }
 
-    /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8) {
-        let bits = self.to_bits();
-        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
-        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
-        let mantissa =
-            if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
-        // Exponent bias + mantissa shift
-        exponent -= 127 + 23;
-        (mantissa as u64, exponent, sign)
+    fn to_bits(self) -> Self::Int {
+        self.to_bits()
     }
 
     fn classify(self) -> FpCategory {
@@ -154,22 +258,21 @@ impl RawFloat for f32 {
 }
 
 impl RawFloat for f64 {
-    const INFINITY: Self = f64::INFINITY;
-    const NEG_INFINITY: Self = f64::NEG_INFINITY;
-    const NAN: Self = f64::NAN;
-    const NEG_NAN: Self = -f64::NAN;
+    type Int = u64;
+
+    const INFINITY: Self = Self::INFINITY;
+    const NEG_INFINITY: Self = Self::NEG_INFINITY;
+    const NAN: Self = Self::NAN;
+    const NEG_NAN: Self = -Self::NAN;
+
+    const BITS: u32 = 64;
+    const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
+    const EXP_MASK: Self::Int = Self::EXP_MASK;
+    const SIG_MASK: Self::Int = Self::MAN_MASK;
 
-    const MANTISSA_EXPLICIT_BITS: usize = 52;
     const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
     const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
-    const MIN_EXPONENT_FAST_PATH: i64 = -22; // assuming FLT_EVAL_METHOD = 0
-    const MAX_EXPONENT_FAST_PATH: i64 = 22;
-    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37;
-    const MINIMUM_EXPONENT: i32 = -1023;
-    const INFINITE_POWER: i32 = 0x7FF;
-    const SIGN_INDEX: usize = 63;
     const SMALLEST_POWER_OF_TEN: i32 = -342;
-    const LARGEST_POWER_OF_TEN: i32 = 308;
 
     #[inline]
     fn from_u64(v: u64) -> Self {
@@ -190,19 +293,8 @@ impl RawFloat for f64 {
         TABLE[exponent & 31]
     }
 
-    /// Returns the mantissa, exponent and sign as integers.
-    fn integer_decode(self) -> (u64, i16, i8) {
-        let bits = self.to_bits();
-        let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
-        let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
-        let mantissa = if exponent == 0 {
-            (bits & 0xfffffffffffff) << 1
-        } else {
-            (bits & 0xfffffffffffff) | 0x10000000000000
-        };
-        // Exponent bias + mantissa shift
-        exponent -= 1023 + 52;
-        (mantissa, exponent, sign)
+    fn to_bits(self) -> Self::Int {
+        self.to_bits()
     }
 
     fn classify(self) -> FpCategory {
diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs
index 01642e1b111..f84929a03c1 100644
--- a/library/core/src/num/dec2flt/lemire.rs
+++ b/library/core/src/num/dec2flt/lemire.rs
@@ -38,7 +38,7 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
     // Normalize our significant digits, so the most-significant bit is set.
     let lz = w.leading_zeros();
     w <<= lz;
-    let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_EXPLICIT_BITS + 3);
+    let (lo, hi) = compute_product_approx(q, w, F::SIG_BITS as usize + 3);
     if lo == 0xFFFF_FFFF_FFFF_FFFF {
         // If we have failed to approximate w x 5^-q with our 128-bit value.
         // Since the addition of 1 could lead to an overflow which could then
@@ -61,8 +61,8 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
         }
     }
     let upperbit = (hi >> 63) as i32;
-    let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3);
-    let mut power2 = power(q as i32) + upperbit - lz as i32 - F::MINIMUM_EXPONENT;
+    let mut mantissa = hi >> (upperbit + 64 - F::SIG_BITS as i32 - 3);
+    let mut power2 = power(q as i32) + upperbit - lz as i32 - F::EXP_MIN + 1;
     if power2 <= 0 {
         if -power2 + 1 >= 64 {
             // Have more than 64 bits below the minimum exponent, must be 0.
@@ -72,8 +72,8 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
         mantissa >>= -power2 + 1;
         mantissa += mantissa & 1;
         mantissa >>= 1;
-        power2 = (mantissa >= (1_u64 << F::MANTISSA_EXPLICIT_BITS)) as i32;
-        return BiasedFp { f: mantissa, e: power2 };
+        power2 = (mantissa >= (1_u64 << F::SIG_BITS)) as i32;
+        return BiasedFp { m: mantissa, p_biased: power2 };
     }
     // Need to handle rounding ties. Normally, we need to round up,
     // but if we fall right in between and we have an even basis, we
@@ -89,8 +89,8 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
     if lo <= 1
         && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64
         && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64
-        && mantissa & 3 == 1
-        && (mantissa << (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3)) == hi
+        && mantissa & 0b11 == 0b01
+        && (mantissa << (upperbit + 64 - F::SIG_BITS as i32 - 3)) == hi
     {
         // Zero the lowest bit, so we don't round up.
         mantissa &= !1_u64;
@@ -98,20 +98,20 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
     // Round-to-even, then shift the significant digits into place.
     mantissa += mantissa & 1;
     mantissa >>= 1;
-    if mantissa >= (2_u64 << F::MANTISSA_EXPLICIT_BITS) {
+    if mantissa >= (2_u64 << F::SIG_BITS) {
         // Rounding up overflowed, so the carry bit is set. Set the
         // mantissa to 1 (only the implicit, hidden bit is set) and
         // increase the exponent.
-        mantissa = 1_u64 << F::MANTISSA_EXPLICIT_BITS;
+        mantissa = 1_u64 << F::SIG_BITS;
         power2 += 1;
     }
     // Zero out the hidden bit.
-    mantissa &= !(1_u64 << F::MANTISSA_EXPLICIT_BITS);
+    mantissa &= !(1_u64 << F::SIG_BITS);
     if power2 >= F::INFINITE_POWER {
         // Exponent is above largest normal value, must be infinite.
         return fp_inf;
     }
-    BiasedFp { f: mantissa, e: power2 }
+    BiasedFp { m: mantissa, p_biased: power2 }
 }
 
 /// Calculate a base 2 exponent from a decimal exponent.
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 6dca7406845..d1a0e1db313 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -3,8 +3,8 @@
 //! # Problem statement
 //!
 //! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
-//! fractional (`34`), and exponent (`56`) parts. All parts are optional and interpreted as zero
-//! when missing.
+//! fractional (`34`), and exponent (`56`) parts. All parts are optional and interpreted as a
+//! default value (1 or 0) when missing.
 //!
 //! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal
 //! string. It is well-known that many decimal strings do not have terminating representations in
@@ -67,6 +67,18 @@
 //! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
 //! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
 //! turned into {positive,negative} {zero,infinity}.
+//!
+//! # Notation
+//!
+//! This module uses the same notation as the Lemire paper:
+//!
+//! - `m`: binary mantissa; always nonnegative
+//! - `p`: binary exponent; a signed integer
+//! - `w`: decimal significand; always nonnegative
+//! - `q`: decimal exponent; a signed integer
+//!
+//! This gives `m * 2^p` for the binary floating-point number, with `w * 10^q` as the decimal
+//! equivalent.
 
 #![doc(hidden)]
 #![unstable(
@@ -85,14 +97,14 @@ use crate::fmt;
 use crate::str::FromStr;
 
 mod common;
-mod decimal;
+pub mod decimal;
+pub mod decimal_seq;
 mod fpu;
 mod slow;
 mod table;
 // float is used in flt2dec, and all are used in unit tests.
 pub mod float;
 pub mod lemire;
-pub mod number;
 pub mod parse;
 
 macro_rules! from_str_float_impl {
@@ -220,10 +232,10 @@ pub fn pfe_invalid() -> ParseFloatError {
 }
 
 /// Converts a `BiasedFp` to the closest machine float type.
-fn biased_fp_to_float<T: RawFloat>(x: BiasedFp) -> T {
-    let mut word = x.f;
-    word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS;
-    T::from_u64_bits(word)
+fn biased_fp_to_float<F: RawFloat>(x: BiasedFp) -> F {
+    let mut word = x.m;
+    word |= (x.p_biased as u64) << F::SIG_BITS;
+    F::from_u64_bits(word)
 }
 
 /// Converts a decimal string into a floating point number.
@@ -260,12 +272,15 @@ pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> {
     // redundantly using the Eisel-Lemire algorithm if it was unable to
     // correctly round on the first pass.
     let mut fp = compute_float::<F>(num.exponent, num.mantissa);
-    if num.many_digits && fp.e >= 0 && fp != compute_float::<F>(num.exponent, num.mantissa + 1) {
-        fp.e = -1;
+    if num.many_digits
+        && fp.p_biased >= 0
+        && fp != compute_float::<F>(num.exponent, num.mantissa + 1)
+    {
+        fp.p_biased = -1;
     }
     // Unable to correctly round the float using the Eisel-Lemire algorithm.
     // Fallback to a slower, but always correct algorithm.
-    if fp.e < 0 {
+    if fp.p_biased < 0 {
         fp = parse_long_mantissa::<F>(s);
     }
 
diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs
deleted file mode 100644
index 2538991564a..00000000000
--- a/library/core/src/num/dec2flt/number.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-//! Representation of a float as the significant digits and exponent.
-
-use crate::num::dec2flt::float::RawFloat;
-use crate::num::dec2flt::fpu::set_precision;
-
-#[rustfmt::skip]
-const INT_POW10: [u64; 16] = [
-    1,
-    10,
-    100,
-    1000,
-    10000,
-    100000,
-    1000000,
-    10000000,
-    100000000,
-    1000000000,
-    10000000000,
-    100000000000,
-    1000000000000,
-    10000000000000,
-    100000000000000,
-    1000000000000000,
-];
-
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
-pub struct Number {
-    pub exponent: i64,
-    pub mantissa: u64,
-    pub negative: bool,
-    pub many_digits: bool,
-}
-
-impl Number {
-    /// Detect if the float can be accurately reconstructed from native floats.
-    #[inline]
-    fn is_fast_path<F: RawFloat>(&self) -> bool {
-        F::MIN_EXPONENT_FAST_PATH <= self.exponent
-            && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH
-            && self.mantissa <= F::MAX_MANTISSA_FAST_PATH
-            && !self.many_digits
-    }
-
-    /// The fast path algorithm using machine-sized integers and floats.
-    ///
-    /// This is extracted into a separate function so that it can be attempted before constructing
-    /// a Decimal. This only works if both the mantissa and the exponent
-    /// can be exactly represented as a machine float, since IEE-754 guarantees
-    /// no rounding will occur.
-    ///
-    /// There is an exception: disguised fast-path cases, where we can shift
-    /// powers-of-10 from the exponent to the significant digits.
-    pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
-        // Here we need to work around <https://github.com/rust-lang/rust/issues/114479>.
-        // The fast path crucially depends on arithmetic being rounded to the correct number of bits
-        // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
-        // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
-        // The `set_precision` function takes care of setting the precision on architectures which
-        // require setting it by changing the global state (like the control word of the x87 FPU).
-        let _cw = set_precision::<F>();
-
-        if self.is_fast_path::<F>() {
-            let mut value = if self.exponent <= F::MAX_EXPONENT_FAST_PATH {
-                // normal fast path
-                let value = F::from_u64(self.mantissa);
-                if self.exponent < 0 {
-                    value / F::pow10_fast_path((-self.exponent) as _)
-                } else {
-                    value * F::pow10_fast_path(self.exponent as _)
-                }
-            } else {
-                // disguised fast path
-                let shift = self.exponent - F::MAX_EXPONENT_FAST_PATH;
-                let mantissa = self.mantissa.checked_mul(INT_POW10[shift as usize])?;
-                if mantissa > F::MAX_MANTISSA_FAST_PATH {
-                    return None;
-                }
-                F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _)
-            };
-            if self.negative {
-                value = -value;
-            }
-            Some(value)
-        } else {
-            None
-        }
-    }
-}
diff --git a/library/core/src/num/dec2flt/parse.rs b/library/core/src/num/dec2flt/parse.rs
index 06ee8e95fbc..e38fedc58be 100644
--- a/library/core/src/num/dec2flt/parse.rs
+++ b/library/core/src/num/dec2flt/parse.rs
@@ -1,8 +1,8 @@
 //! Functions to parse floating-point numbers.
 
 use crate::num::dec2flt::common::{ByteSlice, is_8digits};
+use crate::num::dec2flt::decimal::Decimal;
 use crate::num::dec2flt::float::RawFloat;
-use crate::num::dec2flt::number::Number;
 
 const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
 
@@ -100,7 +100,7 @@ fn parse_scientific(s_ref: &mut &[u8]) -> Option<i64> {
 ///
 /// This creates a representation of the float as the
 /// significant digits and the decimal exponent.
-fn parse_partial_number(mut s: &[u8]) -> Option<(Number, usize)> {
+fn parse_partial_number(mut s: &[u8]) -> Option<(Decimal, usize)> {
     debug_assert!(!s.is_empty());
 
     // parse initial digits before dot
@@ -146,7 +146,7 @@ fn parse_partial_number(mut s: &[u8]) -> Option<(Number, usize)> {
 
     // handle uncommon case with many digits
     if n_digits <= 19 {
-        return Some((Number { exponent, mantissa, negative: false, many_digits: false }, len));
+        return Some((Decimal { exponent, mantissa, negative: false, many_digits: false }, len));
     }
 
     n_digits -= 19;
@@ -179,13 +179,13 @@ fn parse_partial_number(mut s: &[u8]) -> Option<(Number, usize)> {
         exponent += exp_number;
     }
 
-    Some((Number { exponent, mantissa, negative: false, many_digits }, len))
+    Some((Decimal { exponent, mantissa, negative: false, many_digits }, len))
 }
 
 /// Try to parse a non-special floating point number,
 /// as well as two slices with integer and fractional parts
 /// and the parsed exponent.
-pub fn parse_number(s: &[u8]) -> Option<Number> {
+pub fn parse_number(s: &[u8]) -> Option<Decimal> {
     if let Some((float, rest)) = parse_partial_number(s) {
         if rest == s.len() {
             return Some(float);
diff --git a/library/core/src/num/dec2flt/slow.rs b/library/core/src/num/dec2flt/slow.rs
index 85d4b13284b..3baed426523 100644
--- a/library/core/src/num/dec2flt/slow.rs
+++ b/library/core/src/num/dec2flt/slow.rs
@@ -1,7 +1,7 @@
 //! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round.
 
 use crate::num::dec2flt::common::BiasedFp;
-use crate::num::dec2flt::decimal::{Decimal, parse_decimal};
+use crate::num::dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
 use crate::num::dec2flt::float::RawFloat;
 
 /// Parse the significant digits and biased, binary exponent of a float.
@@ -36,7 +36,7 @@ pub(crate) fn parse_long_mantissa<F: RawFloat>(s: &[u8]) -> BiasedFp {
     let fp_zero = BiasedFp::zero_pow2(0);
     let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER);
 
-    let mut d = parse_decimal(s);
+    let mut d = parse_decimal_seq(s);
 
     // Short-circuit if the value can only be a literal 0 or infinity.
     if d.num_digits == 0 || d.decimal_point < -324 {
@@ -50,7 +50,7 @@ pub(crate) fn parse_long_mantissa<F: RawFloat>(s: &[u8]) -> BiasedFp {
         let n = d.decimal_point as usize;
         let shift = get_shift(n);
         d.right_shift(shift);
-        if d.decimal_point < -Decimal::DECIMAL_POINT_RANGE {
+        if d.decimal_point < -DecimalSeq::DECIMAL_POINT_RANGE {
             return fp_zero;
         }
         exp2 += shift as i32;
@@ -67,43 +67,43 @@ pub(crate) fn parse_long_mantissa<F: RawFloat>(s: &[u8]) -> BiasedFp {
             get_shift((-d.decimal_point) as _)
         };
         d.left_shift(shift);
-        if d.decimal_point > Decimal::DECIMAL_POINT_RANGE {
+        if d.decimal_point > DecimalSeq::DECIMAL_POINT_RANGE {
             return fp_inf;
         }
         exp2 -= shift as i32;
     }
     // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2].
     exp2 -= 1;
-    while (F::MINIMUM_EXPONENT + 1) > exp2 {
-        let mut n = ((F::MINIMUM_EXPONENT + 1) - exp2) as usize;
+    while F::EXP_MIN > exp2 {
+        let mut n = (F::EXP_MIN - exp2) as usize;
         if n > MAX_SHIFT {
             n = MAX_SHIFT;
         }
         d.right_shift(n);
         exp2 += n as i32;
     }
-    if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER {
+    if (exp2 - F::EXP_MIN + 1) >= F::INFINITE_POWER {
         return fp_inf;
     }
     // Shift the decimal to the hidden bit, and then round the value
     // to get the high mantissa+1 bits.
-    d.left_shift(F::MANTISSA_EXPLICIT_BITS + 1);
+    d.left_shift(F::SIG_BITS as usize + 1);
     let mut mantissa = d.round();
-    if mantissa >= (1_u64 << (F::MANTISSA_EXPLICIT_BITS + 1)) {
+    if mantissa >= (1_u64 << (F::SIG_BITS + 1)) {
         // Rounding up overflowed to the carry bit, need to
         // shift back to the hidden bit.
         d.right_shift(1);
         exp2 += 1;
         mantissa = d.round();
-        if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER {
+        if (exp2 - F::EXP_MIN + 1) >= F::INFINITE_POWER {
             return fp_inf;
         }
     }
-    let mut power2 = exp2 - F::MINIMUM_EXPONENT;
-    if mantissa < (1_u64 << F::MANTISSA_EXPLICIT_BITS) {
+    let mut power2 = exp2 - F::EXP_MIN + 1;
+    if mantissa < (1_u64 << F::SIG_BITS) {
         power2 -= 1;
     }
     // Zero out all the bits above the explicit mantissa bits.
-    mantissa &= (1_u64 << F::MANTISSA_EXPLICIT_BITS) - 1;
-    BiasedFp { f: mantissa, e: power2 }
+    mantissa &= (1_u64 << F::SIG_BITS) - 1;
+    BiasedFp { m: mantissa, p_biased: power2 }
 }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index a200fd53186..de1557ccc90 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -493,13 +493,13 @@ impl f32 {
     pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
 
     /// Sign bit
-    const SIGN_MASK: u32 = 0x8000_0000;
+    pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
 
     /// Exponent mask
-    const EXP_MASK: u32 = 0x7f80_0000;
+    pub(crate) const EXP_MASK: u32 = 0x7f80_0000;
 
     /// Mantissa mask
-    const MAN_MASK: u32 = 0x007f_ffff;
+    pub(crate) const MAN_MASK: u32 = 0x007f_ffff;
 
     /// Minimum representable positive value (min subnormal)
     const TINY_BITS: u32 = 0x1;
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index de63a462b61..65b5f3b9af0 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -492,13 +492,13 @@ impl f64 {
     pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
 
     /// Sign bit
-    const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
+    pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
 
     /// Exponent mask
-    const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
+    pub(crate) const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
 
     /// Mantissa mask
-    const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
+    pub(crate) const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
 
     /// Minimum representable positive value (min subnormal)
     const TINY_BITS: u64 = 0x1;
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 6984100e498..deb54c8ba34 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -493,7 +493,7 @@ macro_rules! shl_impl_all {
     )*)
 }
 
-shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
+shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 
 /// The right shift operator `>>`. Note that because this trait is implemented
 /// for all integer types with multiple right-hand-side types, Rust's type
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index e0c442e5292..1935268cda8 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -827,7 +827,7 @@ pub trait RangeBounds<T: ?Sized> {
     }
 
     /// Returns `true` if the range contains no items.
-    /// One-sided ranges (`RangeFrom`, etc) always return `true`.
+    /// One-sided ranges (`RangeFrom`, etc) always return `false`.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 7a2764206e8..f991cc4ae2d 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -78,7 +78,7 @@ pub use raw::{from_raw_parts, from_raw_parts_mut};
 
 /// Calculates the direction and split point of a one-sided range.
 ///
-/// This is a helper function for `take` and `take_mut` that returns
+/// This is a helper function for `split_off` and `split_off_mut` that returns
 /// the direction of the split (front or back) as well as the index at
 /// which to split. Returns `None` if the split index would overflow.
 #[inline]
@@ -4313,8 +4313,6 @@ impl<T> [T] {
     /// Splitting off the first three elements of a slice:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
     /// let mut first_three = slice.split_off(..3).unwrap();
     ///
@@ -4325,8 +4323,6 @@ impl<T> [T] {
     /// Splitting off the last two elements of a slice:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
     /// let mut tail = slice.split_off(2..).unwrap();
     ///
@@ -4337,8 +4333,6 @@ impl<T> [T] {
     /// Getting `None` when `range` is out of bounds:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
     ///
     /// assert_eq!(None, slice.split_off(5..));
@@ -4349,7 +4343,7 @@ impl<T> [T] {
     /// ```
     #[inline]
     #[must_use = "method does not modify the slice if the range is out of bounds"]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off<'a, R: OneSidedRange<usize>>(
         self: &mut &'a Self,
         range: R,
@@ -4385,8 +4379,6 @@ impl<T> [T] {
     /// Splitting off the first three elements of a slice:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
     /// let mut first_three = slice.split_off_mut(..3).unwrap();
     ///
@@ -4397,8 +4389,6 @@ impl<T> [T] {
     /// Taking the last two elements of a slice:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
     /// let mut tail = slice.split_off_mut(2..).unwrap();
     ///
@@ -4409,8 +4399,6 @@ impl<T> [T] {
     /// Getting `None` when `range` is out of bounds:
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
     ///
     /// assert_eq!(None, slice.split_off_mut(5..));
@@ -4421,7 +4409,7 @@ impl<T> [T] {
     /// ```
     #[inline]
     #[must_use = "method does not modify the slice if the range is out of bounds"]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off_mut<'a, R: OneSidedRange<usize>>(
         self: &mut &'a mut Self,
         range: R,
@@ -4451,8 +4439,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &[_] = &['a', 'b', 'c'];
     /// let first = slice.split_off_first().unwrap();
     ///
@@ -4460,7 +4446,7 @@ impl<T> [T] {
     /// assert_eq!(first, &'a');
     /// ```
     #[inline]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> {
         let (first, rem) = self.split_first()?;
         *self = rem;
@@ -4475,8 +4461,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
     /// let first = slice.split_off_first_mut().unwrap();
     /// *first = 'd';
@@ -4485,7 +4469,7 @@ impl<T> [T] {
     /// assert_eq!(first, &'d');
     /// ```
     #[inline]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
         let (first, rem) = mem::take(self).split_first_mut()?;
         *self = rem;
@@ -4500,8 +4484,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &[_] = &['a', 'b', 'c'];
     /// let last = slice.split_off_last().unwrap();
     ///
@@ -4509,7 +4491,7 @@ impl<T> [T] {
     /// assert_eq!(last, &'c');
     /// ```
     #[inline]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> {
         let (last, rem) = self.split_last()?;
         *self = rem;
@@ -4524,8 +4506,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_take)]
-    ///
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
     /// let last = slice.split_off_last_mut().unwrap();
     /// *last = 'd';
@@ -4534,7 +4514,7 @@ impl<T> [T] {
     /// assert_eq!(last, &'d');
     /// ```
     #[inline]
-    #[unstable(feature = "slice_take", issue = "62280")]
+    #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
         let (last, rem) = mem::take(self).split_last_mut()?;
         *self = rem;
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 4f21ae5013b..79022fec8a2 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -73,7 +73,6 @@
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(slice_split_once)]
-#![feature(slice_take)]
 #![feature(split_array)]
 #![feature(split_as_slice)]
 #![feature(std_internals)]
@@ -88,7 +87,6 @@
 #![feature(try_find)]
 #![feature(try_trait_v2)]
 #![feature(unsize)]
-#![feature(unsized_tuple_coercion)]
 #![feature(unwrap_infallible)]
 // tidy-alphabetical-end
 #![allow(internal_features)]
diff --git a/library/coretests/tests/num/dec2flt/decimal.rs b/library/coretests/tests/num/dec2flt/decimal.rs
new file mode 100644
index 00000000000..1fa06de692e
--- /dev/null
+++ b/library/coretests/tests/num/dec2flt/decimal.rs
@@ -0,0 +1,28 @@
+use core::num::dec2flt::decimal::Decimal;
+
+type FPath<F> = ((i64, u64, bool, bool), Option<F>);
+
+const FPATHS_F32: &[FPath<f32>] =
+    &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
+const FPATHS_F64: &[FPath<f64>] =
+    &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
+
+#[test]
+fn check_fast_path_f32() {
+    for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F32.iter().copied() {
+        let dec = Decimal { exponent, mantissa, negative, many_digits };
+        let actual = dec.try_fast_path::<f32>();
+
+        assert_eq!(actual, expected);
+    }
+}
+
+#[test]
+fn check_fast_path_f64() {
+    for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F64.iter().copied() {
+        let dec = Decimal { exponent, mantissa, negative, many_digits };
+        let actual = dec.try_fast_path::<f64>();
+
+        assert_eq!(actual, expected);
+    }
+}
diff --git a/library/coretests/tests/num/dec2flt/decimal_seq.rs b/library/coretests/tests/num/dec2flt/decimal_seq.rs
new file mode 100644
index 00000000000..f46ba7c465a
--- /dev/null
+++ b/library/coretests/tests/num/dec2flt/decimal_seq.rs
@@ -0,0 +1,30 @@
+use core::num::dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
+
+#[test]
+fn test_trim() {
+    let mut dec = DecimalSeq::default();
+    let digits = [1, 2, 3, 4];
+
+    dec.digits[0..4].copy_from_slice(&digits);
+    dec.num_digits = 8;
+    dec.trim();
+
+    assert_eq!(dec.digits[0..4], digits);
+    assert_eq!(dec.num_digits, 4);
+}
+
+#[test]
+fn test_parse() {
+    let tests = [("1.234", [1, 2, 3, 4], 1)];
+
+    for (s, exp_digits, decimal_point) in tests {
+        let actual = parse_decimal_seq(s.as_bytes());
+        let mut digits = [0; DecimalSeq::MAX_DIGITS];
+        digits[..exp_digits.len()].copy_from_slice(&exp_digits);
+
+        let expected =
+            DecimalSeq { num_digits: exp_digits.len(), decimal_point, truncated: false, digits };
+
+        assert_eq!(actual, expected);
+    }
+}
diff --git a/library/coretests/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs
index 7a9587a18d0..b5afd3e3b24 100644
--- a/library/coretests/tests/num/dec2flt/float.rs
+++ b/library/coretests/tests/num/dec2flt/float.rs
@@ -12,8 +12,8 @@ fn test_f32_integer_decode() {
 
     // Ignore the "sign" (quiet / signalling flag) of NAN.
     // It can vary between runtime operations and LLVM folding.
-    let (nan_m, nan_e, _nan_s) = f32::NAN.integer_decode();
-    assert_eq!((nan_m, nan_e), (12582912, 105));
+    let (nan_m, nan_p, _nan_s) = f32::NAN.integer_decode();
+    assert_eq!((nan_m, nan_p), (12582912, 105));
 }
 
 #[test]
@@ -28,6 +28,46 @@ fn test_f64_integer_decode() {
 
     // Ignore the "sign" (quiet / signalling flag) of NAN.
     // It can vary between runtime operations and LLVM folding.
-    let (nan_m, nan_e, _nan_s) = f64::NAN.integer_decode();
-    assert_eq!((nan_m, nan_e), (6755399441055744, 972));
+    let (nan_m, nan_p, _nan_s) = f64::NAN.integer_decode();
+    assert_eq!((nan_m, nan_p), (6755399441055744, 972));
+}
+
+/* Sanity checks of computed magic numbers */
+
+#[test]
+fn test_f32_consts() {
+    assert_eq!(<f32 as RawFloat>::INFINITY, f32::INFINITY);
+    assert_eq!(<f32 as RawFloat>::NEG_INFINITY, -f32::INFINITY);
+    assert_eq!(<f32 as RawFloat>::NAN.to_bits(), f32::NAN.to_bits());
+    assert_eq!(<f32 as RawFloat>::NEG_NAN.to_bits(), (-f32::NAN).to_bits());
+    assert_eq!(<f32 as RawFloat>::SIG_BITS, 23);
+    assert_eq!(<f32 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -17);
+    assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 10);
+    assert_eq!(<f32 as RawFloat>::MIN_EXPONENT_FAST_PATH, -10);
+    assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_FAST_PATH, 10);
+    assert_eq!(<f32 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 17);
+    assert_eq!(<f32 as RawFloat>::EXP_MIN, -126);
+    assert_eq!(<f32 as RawFloat>::EXP_SAT, 0xff);
+    assert_eq!(<f32 as RawFloat>::SMALLEST_POWER_OF_TEN, -65);
+    assert_eq!(<f32 as RawFloat>::LARGEST_POWER_OF_TEN, 38);
+    assert_eq!(<f32 as RawFloat>::MAX_MANTISSA_FAST_PATH, 16777216);
+}
+
+#[test]
+fn test_f64_consts() {
+    assert_eq!(<f64 as RawFloat>::INFINITY, f64::INFINITY);
+    assert_eq!(<f64 as RawFloat>::NEG_INFINITY, -f64::INFINITY);
+    assert_eq!(<f64 as RawFloat>::NAN.to_bits(), f64::NAN.to_bits());
+    assert_eq!(<f64 as RawFloat>::NEG_NAN.to_bits(), (-f64::NAN).to_bits());
+    assert_eq!(<f64 as RawFloat>::SIG_BITS, 52);
+    assert_eq!(<f64 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -4);
+    assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 23);
+    assert_eq!(<f64 as RawFloat>::MIN_EXPONENT_FAST_PATH, -22);
+    assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_FAST_PATH, 22);
+    assert_eq!(<f64 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 37);
+    assert_eq!(<f64 as RawFloat>::EXP_MIN, -1022);
+    assert_eq!(<f64 as RawFloat>::EXP_SAT, 0x7ff);
+    assert_eq!(<f64 as RawFloat>::SMALLEST_POWER_OF_TEN, -342);
+    assert_eq!(<f64 as RawFloat>::LARGEST_POWER_OF_TEN, 308);
+    assert_eq!(<f64 as RawFloat>::MAX_MANTISSA_FAST_PATH, 9007199254740992);
 }
diff --git a/library/coretests/tests/num/dec2flt/lemire.rs b/library/coretests/tests/num/dec2flt/lemire.rs
index f71bbb7c7a3..0db80fbd525 100644
--- a/library/coretests/tests/num/dec2flt/lemire.rs
+++ b/library/coretests/tests/num/dec2flt/lemire.rs
@@ -1,13 +1,14 @@
+use core::num::dec2flt::float::RawFloat;
 use core::num::dec2flt::lemire::compute_float;
 
 fn compute_float32(q: i64, w: u64) -> (i32, u64) {
     let fp = compute_float::<f32>(q, w);
-    (fp.e, fp.f)
+    (fp.p_biased, fp.m)
 }
 
 fn compute_float64(q: i64, w: u64) -> (i32, u64) {
     let fp = compute_float::<f64>(q, w);
-    (fp.e, fp.f)
+    (fp.p_biased, fp.m)
 }
 
 #[test]
@@ -27,6 +28,11 @@ fn compute_float_f32_rounding() {
     // Let's check the lines to see if anything is different in table...
     assert_eq!(compute_float32(-10, 167772190000000000), (151, 2));
     assert_eq!(compute_float32(-10, 167772200000000000), (151, 2));
+
+    // Check the rounding point between infinity and the next representable number down
+    assert_eq!(compute_float32(38, 3), (f32::INFINITE_POWER - 1, 6402534));
+    assert_eq!(compute_float32(38, 4), (f32::INFINITE_POWER, 0)); // infinity
+    assert_eq!(compute_float32(20, 3402823470000000000), (f32::INFINITE_POWER - 1, 8388607));
 }
 
 #[test]
diff --git a/library/coretests/tests/num/dec2flt/mod.rs b/library/coretests/tests/num/dec2flt/mod.rs
index 874e0ec7093..a9025be5ca7 100644
--- a/library/coretests/tests/num/dec2flt/mod.rs
+++ b/library/coretests/tests/num/dec2flt/mod.rs
@@ -1,5 +1,7 @@
 #![allow(overflowing_literals)]
 
+mod decimal;
+mod decimal_seq;
 mod float;
 mod lemire;
 mod parse;
diff --git a/library/coretests/tests/num/dec2flt/parse.rs b/library/coretests/tests/num/dec2flt/parse.rs
index 4a5d24ba7d5..59be3915052 100644
--- a/library/coretests/tests/num/dec2flt/parse.rs
+++ b/library/coretests/tests/num/dec2flt/parse.rs
@@ -1,9 +1,9 @@
-use core::num::dec2flt::number::Number;
+use core::num::dec2flt::decimal::Decimal;
 use core::num::dec2flt::parse::parse_number;
 use core::num::dec2flt::{dec2flt, pfe_invalid};
 
-fn new_number(e: i64, m: u64) -> Number {
-    Number { exponent: e, mantissa: m, negative: false, many_digits: false }
+fn new_dec(e: i64, m: u64) -> Decimal {
+    Decimal { exponent: e, mantissa: m, negative: false, many_digits: false }
 }
 
 #[test]
@@ -31,23 +31,23 @@ fn invalid_chars() {
     }
 }
 
-fn parse_positive(s: &[u8]) -> Option<Number> {
+fn parse_positive(s: &[u8]) -> Option<Decimal> {
     parse_number(s)
 }
 
 #[test]
 fn valid() {
-    assert_eq!(parse_positive(b"123.456e789"), Some(new_number(786, 123456)));
-    assert_eq!(parse_positive(b"123.456e+789"), Some(new_number(786, 123456)));
-    assert_eq!(parse_positive(b"123.456e-789"), Some(new_number(-792, 123456)));
-    assert_eq!(parse_positive(b".050"), Some(new_number(-3, 50)));
-    assert_eq!(parse_positive(b"999"), Some(new_number(0, 999)));
-    assert_eq!(parse_positive(b"1.e300"), Some(new_number(300, 1)));
-    assert_eq!(parse_positive(b".1e300"), Some(new_number(299, 1)));
-    assert_eq!(parse_positive(b"101e-33"), Some(new_number(-33, 101)));
+    assert_eq!(parse_positive(b"123.456e789"), Some(new_dec(786, 123456)));
+    assert_eq!(parse_positive(b"123.456e+789"), Some(new_dec(786, 123456)));
+    assert_eq!(parse_positive(b"123.456e-789"), Some(new_dec(-792, 123456)));
+    assert_eq!(parse_positive(b".050"), Some(new_dec(-3, 50)));
+    assert_eq!(parse_positive(b"999"), Some(new_dec(0, 999)));
+    assert_eq!(parse_positive(b"1.e300"), Some(new_dec(300, 1)));
+    assert_eq!(parse_positive(b".1e300"), Some(new_dec(299, 1)));
+    assert_eq!(parse_positive(b"101e-33"), Some(new_dec(-33, 101)));
     let zeros = "0".repeat(25);
     let s = format!("1.5e{zeros}");
-    assert_eq!(parse_positive(s.as_bytes()), Some(new_number(-1, 15)));
+    assert_eq!(parse_positive(s.as_bytes()), Some(new_dec(-1, 15)));
 }
 
 macro_rules! assert_float_result_bits_eq {
@@ -58,6 +58,21 @@ macro_rules! assert_float_result_bits_eq {
 }
 
 #[test]
+fn regression() {
+    // These showed up in fuzz tests when the minimum exponent was incorrect.
+    assert_float_result_bits_eq!(
+        0x0,
+        f64,
+        "3313756768023998018398807867233977556112078681253148176737587500333136120852692315608454494981109839693784033457129423181787087843504060087613228932431e-475"
+    );
+    assert_float_result_bits_eq!(
+        0x0,
+        f64,
+        "5298127456259331337220.92759278003098321644501973966679724599271041396379712108366679824365568578569680024083293475291869842408884554511641179110778276695274832779269225510492006696321279587846006535230380114430977056662212751544508159333199129106162019382177820713609e-346"
+    );
+}
+
+#[test]
 fn issue31109() {
     // Regression test for #31109.
     // Ensure the test produces a valid float with the expected bit pattern.
diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs
index 0c9f9b338b0..c5fd7f01410 100644
--- a/library/coretests/tests/ptr.rs
+++ b/library/coretests/tests/ptr.rs
@@ -525,31 +525,24 @@ fn ptr_metadata() {
     assert_eq!(metadata("foo"), 3_usize);
     assert_eq!(metadata(&[4, 7][..]), 2_usize);
 
-    let dst_tuple: &(bool, [u8]) = &(true, [0x66, 0x6F, 0x6F]);
     let dst_struct: &Pair<bool, [u8]> = &Pair(true, [0x66, 0x6F, 0x6F]);
-    assert_eq!(metadata(dst_tuple), 3_usize);
     assert_eq!(metadata(dst_struct), 3_usize);
     unsafe {
-        let dst_tuple: &(bool, str) = std::mem::transmute(dst_tuple);
         let dst_struct: &Pair<bool, str> = std::mem::transmute(dst_struct);
-        assert_eq!(&dst_tuple.1, "foo");
         assert_eq!(&dst_struct.1, "foo");
-        assert_eq!(metadata(dst_tuple), 3_usize);
         assert_eq!(metadata(dst_struct), 3_usize);
     }
 
     let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug);
     let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display);
     let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display);
-    let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display));
-    let vtable_5: DynMetadata<dyn Display> =
+    let vtable_4: DynMetadata<dyn Display> =
         metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
     unsafe {
         let address_1: *const () = std::mem::transmute(vtable_1);
         let address_2: *const () = std::mem::transmute(vtable_2);
         let address_3: *const () = std::mem::transmute(vtable_3);
         let address_4: *const () = std::mem::transmute(vtable_4);
-        let address_5: *const () = std::mem::transmute(vtable_5);
         // Different trait => different vtable pointer
         assert_ne!(address_1, address_2);
         // Different erased type => different vtable pointer
@@ -558,7 +551,6 @@ fn ptr_metadata() {
         // This is *not guaranteed*, so we skip it in Miri.
         if !cfg!(miri) {
             assert_eq!(address_3, address_4);
-            assert_eq!(address_3, address_5);
         }
     }
 }
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
index 1c5c8a9ebf2..fe356dcc43c 100644
--- a/library/coretests/tests/slice.rs
+++ b/library/coretests/tests/slice.rs
@@ -5,8 +5,6 @@ use core::num::NonZero;
 use core::ops::{Range, RangeInclusive};
 use core::slice;
 
-use rand::seq::IndexedRandom;
-
 #[test]
 fn test_position() {
     let b = [1, 2, 3, 5, 5];
@@ -1810,6 +1808,7 @@ fn select_nth_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
 
     use rand::Rng;
+    use rand::seq::IndexedRandom;
 
     let mut rng = crate::test_rng();
 
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index f4d4894c1bb..f762d205463 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.148" }
+compiler_builtins = { version = "=0.1.150" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
@@ -35,7 +35,7 @@ miniz_oxide = { version = "0.8.0", optional = true, default-features = false }
 addr2line = { version = "0.24.0", optional = true, default-features = false }
 
 [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
-libc = { version = "0.2.169", default-features = false, features = [
+libc = { version = "0.2.170", default-features = false, features = [
     'rustc-dep-of-std',
 ], public = true }
 
diff --git a/library/std/build.rs b/library/std/build.rs
index 723d1eb02e0..9df35ce3cc8 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -12,6 +12,11 @@ fn main() {
         .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
         .parse()
         .unwrap();
+    let target_features: Vec<_> = env::var("CARGO_CFG_TARGET_FEATURE")
+        .unwrap_or_default()
+        .split(",")
+        .map(ToOwned::to_owned)
+        .collect();
     let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
 
     println!("cargo:rustc-check-cfg=cfg(netbsd10)");
@@ -101,6 +106,8 @@ fn main() {
         ("s390x", _) => false,
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
         ("arm64ec", _) => false,
+        // LLVM crash <https://github.com/llvm/llvm-project/issues/129394>
+        ("aarch64", _) if !target_features.iter().any(|f| f == "neon") => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
         ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
         // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 57e235c3efe..4314c8a0b18 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2857,9 +2857,11 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// See [`fs::remove_file`] and [`fs::remove_dir`].
 ///
-/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root `path`.
-/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent.
-/// Additionally, `remove_dir_all` will also fail if the `path` is not a directory.
+/// [`remove_dir_all`] will fail if [`remove_dir`] or [`remove_file`] fail on *any* constituent
+/// paths, *including* the root `path`. Consequently,
+///
+/// - The directory you are deleting *must* exist, meaning that this function is *not idempotent*.
+/// - [`remove_dir_all`] will fail if the `path` is *not* a directory.
 ///
 /// Consider ignoring the error if validating the removal is not required for your use case.
 ///
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 980ea1478e0..7f610bc88bf 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2534,7 +2534,7 @@ pub trait BufRead: Read {
     fn read_line(&mut self, buf: &mut String) -> Result<usize> {
         // Note that we are not calling the `.read_until` method here, but
         // rather our hardcoded implementation. For more details as to why, see
-        // the comments in `read_to_end`.
+        // the comments in `default_read_to_string`.
         unsafe { append_to_string(buf, |b| read_until(self, b'\n', b)) }
     }
 
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 017862c7f3a..ce46241f8e8 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -575,6 +575,11 @@ impl fmt::Debug for StdinLock<'_> {
 /// output stream. Access is also synchronized via a lock and explicit control
 /// over locking is available via the [`lock`] method.
 ///
+/// By default, the handle is line-buffered when connected to a terminal, meaning
+/// it flushes automatically when a newline (`\n`) is encountered. For immediate
+/// output, you can manually call the [`flush`] method. When the handle goes out
+/// of scope, the buffer is automatically flushed.
+///
 /// Created by the [`io::stdout`] method.
 ///
 /// ### Note: Windows Portability Considerations
@@ -590,6 +595,7 @@ impl fmt::Debug for StdinLock<'_> {
 /// standard library or via raw Windows API calls, will fail.
 ///
 /// [`lock`]: Stdout::lock
+/// [`flush`]: Write::flush
 /// [`io::stdout`]: stdout
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdout {
@@ -604,6 +610,11 @@ pub struct Stdout {
 /// This handle implements the [`Write`] trait, and is constructed via
 /// the [`Stdout::lock`] method. See its documentation for more.
 ///
+/// By default, the handle is line-buffered when connected to a terminal, meaning
+/// it flushes automatically when a newline (`\n`) is encountered. For immediate
+/// output, you can manually call the [`flush`] method. When the handle goes out
+/// of scope, the buffer is automatically flushed.
+///
 /// ### Note: Windows Portability Considerations
 ///
 /// When operating in a console, the Windows implementation of this stream does not support
@@ -615,6 +626,8 @@ pub struct Stdout {
 /// the contained handle will be null. In such cases, the standard library's `Read` and
 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
 /// standard library or via raw Windows API calls, will fail.
+///
+/// [`flush`]: Write::flush
 #[must_use = "if unused stdout will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
@@ -629,6 +642,11 @@ static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLoc
 /// is synchronized via a mutex. If you need more explicit control over
 /// locking, see the [`Stdout::lock`] method.
 ///
+/// By default, the handle is line-buffered when connected to a terminal, meaning
+/// it flushes automatically when a newline (`\n`) is encountered. For immediate
+/// output, you can manually call the [`flush`] method. When the handle goes out
+/// of scope, the buffer is automatically flushed.
+///
 /// ### Note: Windows Portability Considerations
 ///
 /// When operating in a console, the Windows implementation of this stream does not support
@@ -669,6 +687,22 @@ static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLoc
 ///     Ok(())
 /// }
 /// ```
+///
+/// Ensuring output is flushed immediately:
+///
+/// ```no_run
+/// use std::io::{self, Write};
+///
+/// fn main() -> io::Result<()> {
+///     let mut stdout = io::stdout();
+///     stdout.write_all(b"hello, ")?;
+///     stdout.flush()?;                // Manual flush
+///     stdout.write_all(b"world!\n")?; // Automatically flushed
+///     Ok(())
+/// }
+/// ```
+///
+/// [`flush`]: Write::flush
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "io_stdout")]
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index cb6aacd0063..cca2312c4f9 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -10,7 +10,7 @@
 //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
 
 use r_efi::efi::{self, Guid};
-use r_efi::protocols::{device_path, device_path_to_text, shell};
+use r_efi::protocols::{device_path, device_path_to_text, service_binding, shell};
 
 use crate::ffi::{OsStr, OsString};
 use crate::io::{self, const_error};
@@ -500,3 +500,62 @@ pub(crate) fn get_device_path_from_map(map: &Path) -> io::Result<BorrowedDeviceP
 
     Ok(BorrowedDevicePath::new(protocol))
 }
+
+/// Helper for UEFI Protocols which are created and destroyed using
+/// [EFI_SERVICE_BINDING_PROTCOL](https://uefi.org/specs/UEFI/2.11/11_Protocols_UEFI_Driver_Model.html#efi-service-binding-protocol)
+pub(crate) struct ServiceProtocol {
+    service_guid: r_efi::efi::Guid,
+    handle: NonNull<crate::ffi::c_void>,
+    child_handle: NonNull<crate::ffi::c_void>,
+}
+
+impl ServiceProtocol {
+    #[expect(dead_code)]
+    pub(crate) fn open(service_guid: r_efi::efi::Guid) -> io::Result<Self> {
+        let handles = locate_handles(service_guid)?;
+
+        for handle in handles {
+            if let Ok(protocol) = open_protocol::<service_binding::Protocol>(handle, service_guid) {
+                let Ok(child_handle) = Self::create_child(protocol) else {
+                    continue;
+                };
+
+                return Ok(Self { service_guid, handle, child_handle });
+            }
+        }
+
+        Err(io::const_error!(io::ErrorKind::NotFound, "no service binding protocol found"))
+    }
+
+    #[expect(dead_code)]
+    pub(crate) fn child_handle(&self) -> NonNull<crate::ffi::c_void> {
+        self.child_handle
+    }
+
+    fn create_child(
+        sbp: NonNull<service_binding::Protocol>,
+    ) -> io::Result<NonNull<crate::ffi::c_void>> {
+        let mut child_handle: r_efi::efi::Handle = crate::ptr::null_mut();
+        // SAFETY: A new handle is allocated if a pointer to NULL is passed.
+        let r = unsafe { ((*sbp.as_ptr()).create_child)(sbp.as_ptr(), &mut child_handle) };
+
+        if r.is_error() {
+            Err(crate::io::Error::from_raw_os_error(r.as_usize()))
+        } else {
+            NonNull::new(child_handle)
+                .ok_or(const_error!(io::ErrorKind::Other, "null child handle"))
+        }
+    }
+}
+
+impl Drop for ServiceProtocol {
+    fn drop(&mut self) {
+        if let Ok(sbp) = open_protocol::<service_binding::Protocol>(self.handle, self.service_guid)
+        {
+            // SAFETY: Child handle must be allocated by the current service binding protocol.
+            let _ = unsafe {
+                ((*sbp.as_ptr()).destroy_child)(sbp.as_ptr(), self.child_handle.as_ptr())
+            };
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs
index a47c8dbcaaa..d4c09dc2ca0 100644
--- a/library/std/src/sys/pal/uefi/process.rs
+++ b/library/std/src/sys/pal/uefi/process.rs
@@ -757,7 +757,7 @@ mod uefi_command_internal {
 }
 
 /// Create a map of environment variable changes. Allows efficient setting and rolling back of
-/// enviroment variable changes.
+/// environment variable changes.
 ///
 /// Entry: (Old Value, New Value)
 fn env_changes(env: &CommandEnv) -> Option<BTreeMap<EnvKey, (Option<OsString>, Option<OsString>)>> {
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index 1f3abd4cc12..ddea445bb17 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -410,6 +410,7 @@ impl Command {
 
     #[cfg(not(any(
         target_os = "freebsd",
+        target_os = "illumos",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
@@ -427,6 +428,7 @@ impl Command {
     // directly.
     #[cfg(any(
         target_os = "freebsd",
+        target_os = "illumos",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
@@ -584,6 +586,10 @@ impl Command {
         fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
             use crate::sys::weak::weak;
 
+            // POSIX.1-2024 standardizes this function:
+            // https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html.
+            // The _np version is more widely available, though, so try that first.
+
             weak! {
                 fn posix_spawn_file_actions_addchdir_np(
                     *mut libc::posix_spawn_file_actions_t,
@@ -591,7 +597,16 @@ impl Command {
                 ) -> libc::c_int
             }
 
-            posix_spawn_file_actions_addchdir_np.get()
+            weak! {
+                fn posix_spawn_file_actions_addchdir(
+                    *mut libc::posix_spawn_file_actions_t,
+                    *const libc::c_char
+                ) -> libc::c_int
+            }
+
+            posix_spawn_file_actions_addchdir_np
+                .get()
+                .or_else(|| posix_spawn_file_actions_addchdir.get())
         }
 
         /// Get the function pointer for adding a chdir action to a
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")
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
index 57fc601a2e0..91c83fa2f5b 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
@@ -19,7 +19,7 @@
 #![allow(incomplete_features)]
 #![feature(unsized_locals, unsized_fn_params)]
 
-// CHECK-LABEL: emptyfn:
+// CHECK-LABEL: emptyfn{{:|\[}}
 #[no_mangle]
 pub fn emptyfn() {
     // all: __stack_chk_fail
@@ -29,7 +29,7 @@ pub fn emptyfn() {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: array_char
+// CHECK-LABEL: array_char{{:|\[}}
 #[no_mangle]
 pub fn array_char(f: fn(*const char)) {
     let a = ['c'; 1];
@@ -47,7 +47,7 @@ pub fn array_char(f: fn(*const char)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: array_u8_1
+// CHECK-LABEL: array_u8_1{{:|\[}}
 #[no_mangle]
 pub fn array_u8_1(f: fn(*const u8)) {
     let a = [0u8; 1];
@@ -63,7 +63,7 @@ pub fn array_u8_1(f: fn(*const u8)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: array_u8_small:
+// CHECK-LABEL: array_u8_small{{:|\[}}
 #[no_mangle]
 pub fn array_u8_small(f: fn(*const u8)) {
     let a = [0u8; 2];
@@ -80,7 +80,7 @@ pub fn array_u8_small(f: fn(*const u8)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: array_u8_large:
+// CHECK-LABEL: array_u8_large{{:|\[}}
 #[no_mangle]
 pub fn array_u8_large(f: fn(*const u8)) {
     let a = [0u8; 9];
@@ -99,7 +99,7 @@ pub fn array_u8_large(f: fn(*const u8)) {
 #[derive(Copy, Clone)]
 pub struct ByteSizedNewtype(u8);
 
-// CHECK-LABEL: array_bytesizednewtype_9:
+// CHECK-LABEL: array_bytesizednewtype_9{{:|\[}}
 #[no_mangle]
 pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
     let a = [ByteSizedNewtype(0); 9];
@@ -115,7 +115,7 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: local_var_addr_used_indirectly
+// CHECK-LABEL: local_var_addr_used_indirectly{{:|\[}}
 #[no_mangle]
 pub fn local_var_addr_used_indirectly(f: fn(bool)) {
     let a = 5;
@@ -142,7 +142,7 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: local_string_addr_taken
+// CHECK-LABEL: local_string_addr_taken{{:|\[}}
 #[no_mangle]
 pub fn local_string_addr_taken(f: fn(&String)) {
     let x = String::new();
@@ -168,7 +168,7 @@ impl SelfByRef for i32 {
     }
 }
 
-// CHECK-LABEL: local_var_addr_taken_used_locally_only
+// CHECK-LABEL: local_var_addr_taken_used_locally_only{{:|\[}}
 #[no_mangle]
 pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
     let x = factory();
@@ -195,7 +195,7 @@ pub struct Gigastruct {
     members: u64,
 }
 
-// CHECK-LABEL: local_large_var_moved
+// CHECK-LABEL: local_large_var_moved{{:|\[}}
 #[no_mangle]
 pub fn local_large_var_moved(f: fn(Gigastruct)) {
     let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
@@ -224,7 +224,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: local_large_var_cloned
+// CHECK-LABEL: local_large_var_cloned{{:|\[}}
 #[no_mangle]
 pub fn local_large_var_cloned(f: fn(Gigastruct)) {
     f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
@@ -281,7 +281,7 @@ extern "C" {
     fn alloca(size: usize) -> *mut ();
 }
 
-// CHECK-LABEL: alloca_small_compile_time_constant_arg
+// CHECK-LABEL: alloca_small_compile_time_constant_arg{{:|\[}}
 #[no_mangle]
 pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
     f(unsafe { alloca(8) });
@@ -293,7 +293,7 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: alloca_large_compile_time_constant_arg
+// CHECK-LABEL: alloca_large_compile_time_constant_arg{{:|\[}}
 #[no_mangle]
 pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
     f(unsafe { alloca(9) });
@@ -305,7 +305,7 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: alloca_dynamic_arg
+// CHECK-LABEL: alloca_dynamic_arg{{:|\[}}
 #[no_mangle]
 pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
     f(unsafe { alloca(n) });
@@ -324,7 +324,7 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
 // this is support for the "unsized locals" unstable feature:
 // https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
 
-// CHECK-LABEL: unsized_fn_param
+// CHECK-LABEL: unsized_fn_param{{:|\[}}
 #[no_mangle]
 pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
     let n = if l { 1 } else { 2 };
@@ -344,7 +344,7 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
     // missing-NOT: __stack_chk_fail
 }
 
-// CHECK-LABEL: unsized_local
+// CHECK-LABEL: unsized_local{{:|\[}}
 #[no_mangle]
 pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) {
     let n = if l { 1 } else { 2 };
diff --git a/tests/codegen/issues/looping-over-ne-bytes-133528.rs b/tests/codegen/issues/looping-over-ne-bytes-133528.rs
new file mode 100644
index 00000000000..35acf765d69
--- /dev/null
+++ b/tests/codegen/issues/looping-over-ne-bytes-133528.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Copt-level=3
+//@ min-llvm-version: 20
+#![crate_type = "lib"]
+
+/// Ensure the function is properly optimized
+/// In the issue #133528, the function was not getting optimized
+/// whereas, a version with `bytes` wrapped into a `black_box` was optimized
+/// It was probably a LLVM bug that was fixed in LLVM 20
+
+// CHECK-LABEL: @looping_over_ne_bytes
+// CHECK: icmp eq i64 %input, -1
+// CHECK-NEXT: ret i1
+#[no_mangle]
+fn looping_over_ne_bytes(input: u64) -> bool {
+    let bytes = input.to_ne_bytes();
+    bytes.iter().all(|x| *x == !0)
+}
diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs
index b36a5b5de3d..950e0b0c10d 100644
--- a/tests/codegen/slice-init.rs
+++ b/tests/codegen/slice-init.rs
@@ -2,8 +2,6 @@
 
 #![crate_type = "lib"]
 
-use std::mem::MaybeUninit;
-
 // CHECK-LABEL: @zero_sized_elem
 #[no_mangle]
 pub fn zero_sized_elem() {
@@ -78,64 +76,31 @@ pub fn u16_init_one_bytes() -> [u16; N] {
     [const { u16::from_be_bytes([1, 1]) }; N]
 }
 
+// FIXME: undef bytes can just be initialized with the same value as the
+// defined bytes, if the defines bytes are all the same.
 // CHECK-LABEL: @option_none_init
 #[no_mangle]
 pub fn option_none_init() -> [Option<u8>; N] {
     // CHECK-NOT: select
-    // CHECK-NOT: br
-    // CHECK-NOT: switch
-    // CHECK-NOT: icmp
-    // CHECK: call void @llvm.memset.p0
-    [const { None }; N]
-}
-
-// If there is partial provenance or some bytes are initialized and some are not,
-// we can't really do better than initialize bytes or groups of bytes together.
-// CHECK-LABEL: @option_maybe_uninit_init
-#[no_mangle]
-pub fn option_maybe_uninit_init() -> [MaybeUninit<u16>; N] {
-    // CHECK-NOT: select
     // CHECK: br label %repeat_loop_header{{.*}}
     // CHECK-NOT: switch
     // CHECK: icmp
     // CHECK-NOT: call void @llvm.memset.p0
-    [const {
-        let mut val: MaybeUninit<u16> = MaybeUninit::uninit();
-        let ptr = val.as_mut_ptr() as *mut u8;
-        unsafe {
-            ptr.write(0);
-        }
-        val
-    }; N]
+    [None; N]
 }
 
-#[repr(packed)]
-struct Packed {
-    start: u8,
-    ptr: &'static (),
-    rest: u16,
-    rest2: u8,
-}
+use std::mem::MaybeUninit;
 
-// If there is partial provenance or some bytes are initialized and some are not,
-// we can't really do better than initialize bytes or groups of bytes together.
-// CHECK-LABEL: @option_maybe_uninit_provenance
+// FIXME: This could be optimized into a memset.
+// Regression test for <https://github.com/rust-lang/rust/issues/137892>.
 #[no_mangle]
-pub fn option_maybe_uninit_provenance() -> [MaybeUninit<Packed>; N] {
+pub fn half_uninit() -> [(u128, MaybeUninit<u128>); N] {
     // CHECK-NOT: select
     // CHECK: br label %repeat_loop_header{{.*}}
     // CHECK-NOT: switch
     // CHECK: icmp
     // CHECK-NOT: call void @llvm.memset.p0
-    [const {
-        let mut val: MaybeUninit<Packed> = MaybeUninit::uninit();
-        unsafe {
-            let ptr = &raw mut (*val.as_mut_ptr()).ptr;
-            static HAS_ADDR: () = ();
-            ptr.write_unaligned(&HAS_ADDR);
-        }
-        val
-    }; N]
+    [const { (0, MaybeUninit::uninit()) }; N]
 }
 
 // Use an opaque function to prevent rustc from removing useless drops.
diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs
index d82474e18e7..b1bb74708c2 100644
--- a/tests/crashes/129095.rs
+++ b/tests/crashes/129095.rs
@@ -1,10 +1,13 @@
 //@ known-bug: rust-lang/rust#129095
 //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir
 
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
 pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {
     BYTES
 }
 
 pub fn main() {
-    assert_eq!(function_with_bytes::<b"AAAAb">(), &[0x41, 0x41, 0x41, 0x41]);
+    assert_eq!(function_with_bytes::<b"AAAAA">(), &[0x41, 0x41, 0x41, 0x41]);
 }
diff --git a/tests/crashes/132960.rs b/tests/crashes/132960.rs
index 87d0ee7dede..c23a3393429 100644
--- a/tests/crashes/132960.rs
+++ b/tests/crashes/132960.rs
@@ -1,6 +1,6 @@
 //@ known-bug: #132960
 
-#![feature(adt_const_params, const_ptr_read, generic_const_exprs)]
+#![feature(adt_const_params, const_ptr_read, generic_const_exprs, unsized_const_params)]
 
 const fn concat_strs<const A: &'static str, const B: &'static str>() -> &'static str
 where
diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs
deleted file mode 100644
index 916c1559240..00000000000
--- a/tests/crashes/132981.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #132981
-//@compile-flags: -Clink-dead-code=true --crate-type lib
-//@ only-x86_64
-//@ ignore-windows
-// The set of targets this crashes on is really fiddly, because it is deep in our ABI logic. It
-// crashes on x86_64-unknown-linux-gnu, and i686-pc-windows-msvc, but not on
-// x86_64-pc-windows-msvc. If you are trying to fix this crash, don't pay too much attention to the
-// directives.
-
-#![feature(rust_cold_cc)]
-pub extern "rust-cold" fn foo(_: [usize; 3]) {}
diff --git a/tests/crashes/134654.rs b/tests/crashes/134654.rs
index 8a8d18359e9..f2323fe4ecd 100644
--- a/tests/crashes/134654.rs
+++ b/tests/crashes/134654.rs
@@ -2,6 +2,9 @@
 //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir
 //@ only-x86_64
 
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
 fn function_with_bytes<const BYTES:
     &'static [u8; 0xa9008fb6c9d81e42_0e25730562a601c8_u128]>() -> &'static [u8] {
     BYTES
diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs
index 2ce17df824a..a8fd1ae1ff5 100644
--- a/tests/crashes/135128.rs
+++ b/tests/crashes/135128.rs
@@ -1,6 +1,8 @@
 //@ known-bug: #135128
 //@ compile-flags: -Copt-level=1 --edition=2021
 
+#![feature(trivial_bounds)]
+
 async fn return_str() -> str
 where
     str: Sized,
diff --git a/tests/crashes/135570.rs b/tests/crashes/135570.rs
index a9eda97ef9d..7919ceb26d5 100644
--- a/tests/crashes/135570.rs
+++ b/tests/crashes/135570.rs
@@ -2,6 +2,9 @@
 //@compile-flags: -Zvalidate-mir -Zmir-enable-passes=+Inline -Copt-level=0 -Zmir-enable-passes=+GVN
 //@ only-x86_64
 
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
 fn function_with_bytes<const BYTES: &'static [u8; 0xc7b889180b67b07d_bc1a3c88783d35b5_u128]>(
 ) -> &'static [u8] {
     BYTES
diff --git a/tests/debuginfo/unsized.rs b/tests/debuginfo/unsized.rs
index acfe511be7c..17c5e463fba 100644
--- a/tests/debuginfo/unsized.rs
+++ b/tests/debuginfo/unsized.rs
@@ -18,12 +18,6 @@
 // gdb-command:print _box
 // gdb-check:$4 = alloc::boxed::Box<unsized::Foo<dyn core::fmt::Debug>, alloc::alloc::Global> {pointer: [...], vtable: [...]}
 
-// gdb-command:print tuple_slice
-// gdb-check:$5 = &(i32, i32, [i32]) {data_ptr: [...], length: 2}
-
-// gdb-command:print tuple_dyn
-// gdb-check:$6 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]}
-
 // === CDB TESTS ===================================================================================
 
 // cdb-command: g
@@ -48,17 +42,6 @@
 // cdb-check:[+0x000] pointer          : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
 // cdb-check:[...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
 
-// cdb-command:dx tuple_slice
-// cdb-check:tuple_slice      [Type: ref$<tuple$<i32,i32,slice2$<i32> > >]
-// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: tuple$<i32,i32,slice2$<i32> > *]
-// cdb-check:    [...] length           : 0x2 [Type: unsigned [...]int[...]
-
-// cdb-command:dx tuple_dyn
-// cdb-check:tuple_dyn        [Type: ref$<tuple$<i32,i32,dyn$<core::fmt::Debug> > >]
-// cdb-check:    [+0x000] pointer          : 0x[...] [Type: tuple$<i32,i32,dyn$<core::fmt::Debug> > *]
-// cdb-check:    [...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
-
-#![feature(unsized_tuple_coercion)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
@@ -77,10 +60,6 @@ fn main() {
     let c: &Foo<dyn std::fmt::Debug> = &Foo { value: 7i32 };
     let _box: Box<Foo<dyn std::fmt::Debug>> = Box::new(Foo { value: 8i32 });
 
-    // Also check unsized tuples
-    let tuple_slice: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
-    let tuple_dyn: &(i32, i32, dyn std::fmt::Debug) = &(0, 1, &3u64);
-
     zzz(); // #break
 }
 
diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff
index 757617e5940..0615f8132af 100644
--- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff
@@ -7,23 +7,42 @@
       let mut _0: ();
       let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
       let mut _4: I;
++     scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
++         let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
++         let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
++         let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
++     }
   
       bb0: {
           StorageLive(_3);
           _3 = &mut _1;
           StorageLive(_4);
           _4 = move _2;
-          _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
+-         _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_5);
++         _6 = copy (*_3);
++         _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
++         _5 = &mut (*_7);
++         _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable];
       }
   
       bb1: {
-          StorageDead(_4);
-          StorageDead(_3);
-          drop(_1) -> [return: bb2, unwind unreachable];
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb2, unwind unreachable];
++         return;
       }
   
       bb2: {
-          return;
+-         return;
++         StorageDead(_5);
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageDead(_4);
++         StorageDead(_3);
++         drop(_1) -> [return: bb1, unwind unreachable];
       }
   }
   
diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff
index b82961c2815..21b20329d4f 100644
--- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff
@@ -7,31 +7,54 @@
       let mut _0: ();
       let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
       let mut _4: I;
++     scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
++         let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
++         let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
++         let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
++     }
   
       bb0: {
           StorageLive(_3);
           _3 = &mut _1;
           StorageLive(_4);
           _4 = move _2;
-          _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3];
+-         _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3];
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_5);
++         _6 = copy (*_3);
++         _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
++         _5 = &mut (*_7);
++         _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2];
       }
   
       bb1: {
-          StorageDead(_4);
-          StorageDead(_3);
-          drop(_1) -> [return: bb2, unwind: bb4];
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb2, unwind: bb4];
++         return;
       }
   
-      bb2: {
-          return;
+-     bb2: {
+-         return;
++     bb2 (cleanup): {
++         drop(_1) -> [return: bb3, unwind terminate(cleanup)];
       }
   
       bb3 (cleanup): {
-          drop(_1) -> [return: bb4, unwind terminate(cleanup)];
+-         drop(_1) -> [return: bb4, unwind terminate(cleanup)];
++         resume;
       }
   
-      bb4 (cleanup): {
-          resume;
+-     bb4 (cleanup): {
+-         resume;
++     bb4: {
++         StorageDead(_5);
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageDead(_4);
++         StorageDead(_3);
++         drop(_1) -> [return: bb1, unwind: bb3];
       }
   }
   
diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
index abc0ef5c61d..ac0c3ddac76 100644
--- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
+++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
@@ -8,6 +8,6 @@ use std::marker::Tuple;
 // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
 pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
     // CHECK-LABEL: fn call(
-    // CHECK-NOT: inlined
+    // CHECK: (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut)
     mock.call_mut(input)
 }
diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff
index 4fa04b05e89..ecea7a97513 100644
--- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff
@@ -7,6 +7,11 @@
       let _2: ();
       let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
       let mut _4: (i32,);
++     scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
++         let mut _5: &dyn std::ops::Fn(i32);
++         let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
++         let mut _7: *const dyn std::ops::Fn(i32);
++     }
   
       bb0: {
           StorageLive(_2);
@@ -14,19 +19,34 @@
           _3 = &_1;
           StorageLive(_4);
           _4 = (const 1_i32,);
-          _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
+-         _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_5);
++         _6 = copy (*_3);
++         _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
++         _5 = &(*_7);
++         _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb2, unwind unreachable];
       }
   
       bb1: {
++         return;
++     }
++ 
++     bb2: {
++         StorageDead(_5);
++         StorageDead(_7);
++         StorageDead(_6);
           StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           _0 = const ();
-          drop(_1) -> [return: bb2, unwind unreachable];
-      }
-  
-      bb2: {
-          return;
+-         drop(_1) -> [return: bb2, unwind unreachable];
+-     }
+- 
+-     bb2: {
+-         return;
++         drop(_1) -> [return: bb1, unwind unreachable];
       }
   }
   
diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff
index 47fd0ed0799..3a4a528e879 100644
--- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff
@@ -7,6 +7,11 @@
       let _2: ();
       let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
       let mut _4: (i32,);
++     scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
++         let mut _5: &dyn std::ops::Fn(i32);
++         let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
++         let mut _7: *const dyn std::ops::Fn(i32);
++     }
   
       bb0: {
           StorageLive(_2);
@@ -14,27 +19,47 @@
           _3 = &_1;
           StorageLive(_4);
           _4 = (const 1_i32,);
-          _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3];
+-         _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3];
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_5);
++         _6 = copy (*_3);
++         _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
++         _5 = &(*_7);
++         _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb4, unwind: bb2];
       }
   
       bb1: {
-          StorageDead(_4);
-          StorageDead(_3);
-          StorageDead(_2);
-          _0 = const ();
-          drop(_1) -> [return: bb2, unwind: bb4];
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         StorageDead(_2);
+-         _0 = const ();
+-         drop(_1) -> [return: bb2, unwind: bb4];
++         return;
       }
   
-      bb2: {
-          return;
+-     bb2: {
+-         return;
++     bb2 (cleanup): {
++         drop(_1) -> [return: bb3, unwind terminate(cleanup)];
       }
   
       bb3 (cleanup): {
-          drop(_1) -> [return: bb4, unwind terminate(cleanup)];
+-         drop(_1) -> [return: bb4, unwind terminate(cleanup)];
++         resume;
       }
   
-      bb4 (cleanup): {
-          resume;
+-     bb4 (cleanup): {
+-         resume;
++     bb4: {
++         StorageDead(_5);
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageDead(_4);
++         StorageDead(_3);
++         StorageDead(_2);
++         _0 = const ();
++         drop(_1) -> [return: bb1, unwind: bb3];
       }
   }
   
diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs
index bb2da3ac515..e9ab3bef01f 100644
--- a/tests/mir-opt/inline/inline_box_fn.rs
+++ b/tests/mir-opt/inline/inline_box_fn.rs
@@ -5,6 +5,6 @@
 // EMIT_MIR inline_box_fn.call.Inline.diff
 fn call(x: Box<dyn Fn(i32)>) {
     // CHECK-LABEL: fn call(
-    // CHECK-NOT: inlined
+    // CHECK: (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call)
     x(1);
 }
diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff
index 8a6eec3352a..c878b8b6324 100644
--- a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff
@@ -5,9 +5,15 @@
       let mut _0: ();
       let _1: ();
 +     let mut _2: fn() {f};
++     let mut _4: ();
 +     scope 1 (inlined call::<fn() {f}>) {
 +         debug f => _2;
 +         let _3: ();
++         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
++             scope 3 (inlined f) {
++                 let _5: ();
++             }
++         }
 +     }
   
       bb0: {
@@ -16,10 +22,15 @@
 +         StorageLive(_2);
 +         _2 = f;
 +         StorageLive(_3);
-+         _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind unreachable];
++         StorageLive(_4);
++         _4 = const ();
++         StorageLive(_5);
++         _5 = call::<fn() {f}>(f) -> [return: bb1, unwind unreachable];
       }
   
       bb1: {
++         StorageDead(_5);
++         StorageDead(_4);
 +         StorageDead(_3);
 +         StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff
index a24649c1ebd..072b7ab3fa4 100644
--- a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff
@@ -5,9 +5,15 @@
       let mut _0: ();
       let _1: ();
 +     let mut _2: fn() {f};
++     let mut _4: ();
 +     scope 1 (inlined call::<fn() {f}>) {
 +         debug f => _2;
 +         let _3: ();
++         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
++             scope 3 (inlined f) {
++                 let _5: ();
++             }
++         }
 +     }
   
       bb0: {
@@ -16,10 +22,15 @@
 +         StorageLive(_2);
 +         _2 = f;
 +         StorageLive(_3);
-+         _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind continue];
++         StorageLive(_4);
++         _4 = const ();
++         StorageLive(_5);
++         _5 = call::<fn() {f}>(f) -> [return: bb1, unwind continue];
       }
   
       bb1: {
++         StorageDead(_5);
++         StorageDead(_4);
 +         StorageDead(_3);
 +         StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff
index 338dca85e5c..75fc2ea16e3 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff
@@ -5,6 +5,7 @@
       let mut _0: ();
       let _1: (!, !);
 +     let mut _2: fn() -> ! {sleep};
++     let mut _7: ();
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
 +         debug f => _2;
 +         let mut _3: &fn() -> ! {sleep};
@@ -17,6 +18,10 @@
 +                 debug b => _6;
 +             }
 +         }
++         scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
++             scope 5 (inlined sleep) {
++             }
++         }
 +     }
   
       bb0: {
@@ -28,24 +33,13 @@
 +         StorageLive(_6);
 +         StorageLive(_3);
 +         _3 = &_2;
-+         _4 = <fn() -> ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind unreachable];
++         StorageLive(_7);
++         _7 = const ();
++         goto -> bb1;
 +     }
 + 
 +     bb1: {
-+         StorageDead(_3);
-+         StorageLive(_5);
-+         _5 = &_2;
-+         _6 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind unreachable];
-+     }
-+ 
-+     bb2: {
-+         StorageDead(_5);
-+         _1 = (copy _4, copy _6);
-+         drop(_2) -> [return: bb3, unwind unreachable];
-+     }
-+ 
-+     bb3: {
-+         unreachable;
++         goto -> bb1;
       }
   }
   
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff
index a77cb913bfd..407cb24df67 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff
@@ -5,6 +5,7 @@
       let mut _0: ();
       let _1: (!, !);
 +     let mut _2: fn() -> ! {sleep};
++     let mut _8: ();
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
 +         debug f => _2;
 +         let mut _3: &fn() -> ! {sleep};
@@ -18,6 +19,10 @@
 +                 debug b => _6;
 +             }
 +         }
++         scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
++             scope 5 (inlined sleep) {
++             }
++         }
 +     }
   
       bb0: {
@@ -29,40 +34,13 @@
 +         StorageLive(_4);
 +         StorageLive(_3);
 +         _3 = &_2;
-+         _4 = <fn() -> ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind: bb5];
++         StorageLive(_8);
++         _8 = const ();
++         goto -> bb1;
 +     }
 + 
 +     bb1: {
-+         StorageDead(_3);
-+         StorageLive(_5);
-+         _5 = &_2;
-+         _6 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind: bb4];
-+     }
-+ 
-+     bb2: {
-+         StorageDead(_5);
-+         StorageLive(_7);
-+         _7 = move _4;
-+         _1 = (move _7, copy _6);
-+         StorageDead(_7);
-+         StorageDead(_4);
-+         drop(_2) -> [return: bb3, unwind continue];
-+     }
-+ 
-+     bb3: {
-+         unreachable;
-+     }
-+ 
-+     bb4 (cleanup): {
-+         drop(_4) -> [return: bb5, unwind terminate(cleanup)];
-+     }
-+ 
-+     bb5 (cleanup): {
-+         drop(_2) -> [return: bb6, unwind terminate(cleanup)];
-+     }
-+ 
-+     bb6 (cleanup): {
-+         resume;
++         goto -> bb1;
       }
   }
   
diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs
index e1cea3618f1..04ff943e746 100644
--- a/tests/mir-opt/inline/inline_diverging.rs
+++ b/tests/mir-opt/inline/inline_diverging.rs
@@ -26,7 +26,8 @@ pub fn g(i: i32) -> u32 {
 pub fn h() {
     // CHECK-LABEL: fn h(
     // CHECK: (inlined call_twice::<!, fn() -> ! {sleep}>)
-    // CHECK-NOT: inlined
+    // CHECK: (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep}))
+    // CHECK: (inlined sleep)
     call_twice(sleep);
 }
 
diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff
index b9f268df351..14a0c639c3a 100644
--- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff
@@ -10,6 +10,10 @@
       let mut _5: ();
 +     scope 1 (inlined hide_foo) {
 +     }
++     scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
++         scope 3 (inlined foo) {
++         }
++     }
   
       bb0: {
           StorageLive(_2);
@@ -23,22 +27,20 @@
           StorageLive(_5);
           _5 = ();
 -         _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind unreachable];
-+         _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind unreachable];
-      }
-  
+-     }
+- 
 -     bb2: {
-+     bb1: {
           StorageDead(_5);
           StorageDead(_3);
           StorageDead(_4);
           StorageDead(_2);
           _0 = const ();
 -         drop(_1) -> [return: bb3, unwind unreachable];
-+         drop(_1) -> [return: bb2, unwind unreachable];
++         drop(_1) -> [return: bb1, unwind unreachable];
       }
   
 -     bb3: {
-+     bb2: {
++     bb1: {
           return;
       }
   }
diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff
index 8495164df9c..e0a273eb13f 100644
--- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff
@@ -10,6 +10,10 @@
       let mut _5: ();
 +     scope 1 (inlined hide_foo) {
 +     }
++     scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
++         scope 3 (inlined foo) {
++         }
++     }
   
       bb0: {
           StorageLive(_2);
@@ -23,33 +27,29 @@
           StorageLive(_5);
           _5 = ();
 -         _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4];
-+         _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind: bb3];
-      }
-  
+-     }
+- 
 -     bb2: {
-+     bb1: {
           StorageDead(_5);
           StorageDead(_3);
           StorageDead(_4);
           StorageDead(_2);
           _0 = const ();
 -         drop(_1) -> [return: bb3, unwind: bb5];
-+         drop(_1) -> [return: bb2, unwind: bb4];
++         drop(_1) -> [return: bb1, unwind: bb2];
       }
   
 -     bb3: {
-+     bb2: {
++     bb1: {
           return;
       }
   
 -     bb4 (cleanup): {
 -         drop(_1) -> [return: bb5, unwind terminate(cleanup)];
-+     bb3 (cleanup): {
-+         drop(_1) -> [return: bb4, unwind terminate(cleanup)];
-      }
-  
+-     }
+- 
 -     bb5 (cleanup): {
-+     bb4 (cleanup): {
++     bb2 (cleanup): {
           resume;
       }
   }
diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs
index 4eb5c142034..a142d457377 100644
--- a/tests/mir-opt/inline/issue_78442.rs
+++ b/tests/mir-opt/inline/issue_78442.rs
@@ -9,10 +9,9 @@ pub fn bar<P>(
     _baz: P,
 ) {
     // CHECK-LABEL: fn bar(
-    // CHECK: let mut {{.*}}: &fn() {foo};
-    // CHECK: let {{.*}}: fn() {foo};
     // CHECK: (inlined hide_foo)
-    // CHECK-NOT: inlined
+    // CHECK: (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo}))
+    // CHECK: (inlined foo)
     hide_foo()();
 }
 
diff --git a/tests/mir-opt/inline_fn_call_for_fn_def.rs b/tests/mir-opt/inline_fn_call_for_fn_def.rs
new file mode 100644
index 00000000000..7601feda573
--- /dev/null
+++ b/tests/mir-opt/inline_fn_call_for_fn_def.rs
@@ -0,0 +1,19 @@
+//@ test-mir-pass: Inline
+//@ compile-flags: --crate-type=lib -C panic=abort
+
+// EMIT_MIR inline_fn_call_for_fn_def.test.Inline.diff
+
+fn inline_fn(x: impl FnOnce() -> i32) -> i32 {
+    x()
+}
+
+fn yield_number() -> i32 {
+    64
+}
+
+fn test() -> i32 {
+    // CHECK: (inlined inline_fn::<fn() -> i32 {yield_number}>)
+    // CHECK: (inlined <fn() -> i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number}))
+    // CHECK: (inlined yield_number)
+    inline_fn(yield_number)
+}
diff --git a/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff b/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff
new file mode 100644
index 00000000000..aef7aa23970
--- /dev/null
+++ b/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff
@@ -0,0 +1,34 @@
+- // MIR for `test` before Inline
++ // MIR for `test` after Inline
+  
+  fn test() -> i32 {
+      let mut _0: i32;
+- 
+-     bb0: {
+-         _0 = inline_fn::<fn() -> i32 {yield_number}>(yield_number) -> [return: bb1, unwind unreachable];
++     let mut _1: fn() -> i32 {yield_number};
++     scope 1 (inlined inline_fn::<fn() -> i32 {yield_number}>) {
++         let mut _2: fn() -> i32 {yield_number};
++         let mut _3: ();
++         scope 2 (inlined <fn() -> i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number})) {
++             scope 3 (inlined yield_number) {
++             }
++         }
+      }
+  
+-     bb1: {
++     bb0: {
++         StorageLive(_1);
++         _1 = yield_number;
++         StorageLive(_2);
++         _2 = move _1;
++         StorageLive(_3);
++         _3 = ();
++         _0 = const 64_i32;
++         StorageDead(_3);
++         StorageDead(_2);
++         StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir
index 5876c55c52b..5876c55c52b 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir
index f1185353a43..f1185353a43 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir
new file mode 100644
index 00000000000..5876c55c52b
--- /dev/null
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir
@@ -0,0 +1,68 @@
+// MIR for `num_to_digit` after PreCodegen
+
+fn num_to_digit(_1: char) -> u32 {
+    debug num => _1;
+    let mut _0: u32;
+    let mut _4: std::option::Option<u32>;
+    scope 1 (inlined char::methods::<impl char>::is_digit) {
+        let _2: std::option::Option<u32>;
+        scope 2 (inlined Option::<u32>::is_some) {
+            let mut _3: isize;
+        }
+    }
+    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
+        let mut _5: isize;
+        let mut _6: !;
+        scope 4 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);
+        _2 = char::methods::<impl char>::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind unreachable];
+    }
+
+    bb1: {
+        StorageLive(_3);
+        _3 = discriminant(_2);
+        StorageDead(_2);
+        switchInt(move _3) -> [1: bb2, otherwise: bb7];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        StorageLive(_4);
+        _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
+    }
+
+    bb3: {
+        StorageLive(_5);
+        _5 = discriminant(_4);
+        switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
+    }
+
+    bb4: {
+        _6 = option::unwrap_failed() -> unwind unreachable;
+    }
+
+    bb5: {
+        _0 = move ((_4 as Some).0: u32);
+        StorageDead(_5);
+        StorageDead(_4);
+        goto -> bb8;
+    }
+
+    bb6: {
+        unreachable;
+    }
+
+    bb7: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb8;
+    }
+
+    bb8: {
+        return;
+    }
+}
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir
new file mode 100644
index 00000000000..f1185353a43
--- /dev/null
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir
@@ -0,0 +1,68 @@
+// MIR for `num_to_digit` after PreCodegen
+
+fn num_to_digit(_1: char) -> u32 {
+    debug num => _1;
+    let mut _0: u32;
+    let mut _4: std::option::Option<u32>;
+    scope 1 (inlined char::methods::<impl char>::is_digit) {
+        let _2: std::option::Option<u32>;
+        scope 2 (inlined Option::<u32>::is_some) {
+            let mut _3: isize;
+        }
+    }
+    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
+        let mut _5: isize;
+        let mut _6: !;
+        scope 4 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);
+        _2 = char::methods::<impl char>::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        StorageLive(_3);
+        _3 = discriminant(_2);
+        StorageDead(_2);
+        switchInt(move _3) -> [1: bb2, otherwise: bb7];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        StorageLive(_4);
+        _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
+    }
+
+    bb3: {
+        StorageLive(_5);
+        _5 = discriminant(_4);
+        switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
+    }
+
+    bb4: {
+        _6 = option::unwrap_failed() -> unwind continue;
+    }
+
+    bb5: {
+        _0 = move ((_4 as Some).0: u32);
+        StorageDead(_5);
+        StorageDead(_4);
+        goto -> bb8;
+    }
+
+    bb6: {
+        unreachable;
+    }
+
+    bb7: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb8;
+    }
+
+    bb8: {
+        return;
+    }
+}
diff --git a/tests/mir-opt/issues/issue_59352.rs b/tests/mir-opt/issues/issue_59352.rs
index 9024dc976e4..516a712f1db 100644
--- a/tests/mir-opt/issues/issue_59352.rs
+++ b/tests/mir-opt/issues/issue_59352.rs
@@ -1,4 +1,6 @@
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+
 // This test is a mirror of codegen/issue-59352.rs.
 // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
 // as effectively `if x.is_some() { x.unwrap() } else { 0 }`.
diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir
index 4977f39ccef..d22ea54004c 100644
--- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir
@@ -29,6 +29,10 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
                 let mut _12: U;
                 scope 6 {
                     debug x => _10;
+                    scope 7 (inlined ops::function::impls::<impl FnOnce<(T,)> for &mut impl Fn(T) -> U>::call_once) {
+                        debug self => _8;
+                        debug args => _11;
+                    }
                 }
             }
         }
@@ -85,7 +89,7 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
         StorageLive(_12);
         StorageLive(_11);
         _11 = (copy _10,);
-        _12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb10];
+        _12 = <impl Fn(T) -> U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10];
     }
 
     bb7: {
diff --git a/tests/run-make/README.md b/tests/run-make/README.md
index 40359903473..5cdd2fdc523 100644
--- a/tests/run-make/README.md
+++ b/tests/run-make/README.md
@@ -1,32 +1,17 @@
 # The `run-make` test suite
 
-The `run-make` test suite contains tests which are the most flexible out of all
-the [rust-lang/rust](https://github.com/rust-lang/rust) test suites. `run-make`
-tests can basically contain arbitrary code, and are supported by the
-[`run_make_support`] library.
+The `run-make` test suite contains tests which are the most flexible out of all the [rust-lang/rust](https://github.com/rust-lang/rust) test suites. `run-make` tests can basically contain arbitrary code, and are supported by the [`run_make_support`] library.
 
 ## Infrastructure
 
-There are two kinds of run-make tests:
+A `run-make` test is a test recipe source file `rmake.rs` accompanied by its parent directory (e.g. `tests/run-make/foo/rmake.rs` is the `foo` `run-make` test).
 
-1. The new `rmake.rs` version: this allows run-make tests to be written in Rust
-   (with `rmake.rs` as the main test file).
-2. The legacy `Makefile` version: this is what run-make tests were written with
-   before support for `rmake.rs` was introduced.
+The implementation for collecting and building the `rmake.rs` recipes are in [`src/tools/compiletest/src/runtest.rs`](../../src/tools/compiletest/src/runtest.rs), in `run_rmake_test`.
 
-The implementation for collecting and building the `rmake.rs` recipes (or
-`Makefile`s) are in
-[`src/tools/compiletest/src/runtest.rs`](../../src/tools/compiletest/src/runtest.rs),
-in `run_rmake_v2_test` and `run_rmake_legacy_test`.
-
-### Rust-based `run-make` tests: `rmake.rs`
-
-The setup for the `rmake.rs` version is a 3-stage process:
+The setup for the `rmake.rs` can be summarized as a 3-stage process:
 
 1. First, we build the [`run_make_support`] library in bootstrap as a tool lib.
-2. Then, we compile the `rmake.rs` "recipe" linking the support library and its
-   dependencies in, and provide a bunch of env vars. We setup a directory
-   structure within `build/<target>/test/run-make/`
+2. Then, we compile the `rmake.rs` "recipe" linking the support library and its dependencies in, and provide a bunch of env vars. We setup a directory structure within `build/<target>/test/run-make/`
 
    ```
    <test-name>/
@@ -34,15 +19,8 @@ The setup for the `rmake.rs` version is a 3-stage process:
        rmake_out/             # sources from test sources copied over
    ```
 
-   and copy non-`rmake.rs` input support files over to `rmake_out/`. The
-   support library is made available as an [*extern prelude*][extern_prelude].
-3. Finally, we run the recipe binary and set `rmake_out/` as the working
-   directory.
+   and copy non-`rmake.rs` input support files over to `rmake_out/`. The support library is made available as an [*extern prelude*][extern_prelude].
+3. Finally, we run the recipe binary and set `rmake_out/` as the working directory.
 
 [`run_make_support`]: ../../src/tools/run-make-support
 [extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude
-
-### Formatting
-
-Note that files under `tests/` are not formatted by `./x fmt`,
-use `rustfmt tests/path/to/file.rs` to format a specific file if desired.
diff --git a/tests/run-make/a-b-a-linker-guard/rmake.rs b/tests/run-make/a-b-a-linker-guard/rmake.rs
index ee6d655bc76..4428685a6cf 100644
--- a/tests/run-make/a-b-a-linker-guard/rmake.rs
+++ b/tests/run-make/a-b-a-linker-guard/rmake.rs
@@ -1,7 +1,8 @@
-// ignore-tidy-linelength
+// Test that if we build `b` against a version of `a` that has
+// one set of types, it will not run with a dylib that has a different set of types.
 
-// Test that if we build `b` against a version of `a` that has one set of types, it will not run
-// with a dylib that has a different set of types.
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
 
 use run_make_support::{run, run_fail, rustc};
 
diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs
index 30387af428c..73ad248b6f3 100644
--- a/tests/run-make/linker-warning/rmake.rs
+++ b/tests/run-make/linker-warning/rmake.rs
@@ -60,6 +60,8 @@ fn main() {
                 regex::escape(run_make_support::build_root().to_str().unwrap()),
                 "/build-root",
             )
+            .normalize(r#""[^"]*\/symbols.o""#, "\"/symbols.o\"")
+            .normalize(r#""[^"]*\/raw-dylibs""#, "\"/raw-dylibs\"")
             .run();
     }
 
diff --git a/tests/run-make/linker-warning/short-error.txt b/tests/run-make/linker-warning/short-error.txt
index dd3b742bbfd..a7f48af885a 100644
--- a/tests/run-make/linker-warning/short-error.txt
+++ b/tests/run-make/linker-warning/short-error.txt
@@ -1,6 +1,6 @@
 error: linking with `./fake-linker` failed: exit status: 1
   |
-  = note:  "./fake-linker" "-m64" "/tmp/rustc/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error"
+  = note:  "./fake-linker" "-m64" "/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error"
   = note: some arguments are omitted. use `--verbose` to show all linker arguments
   = note: error: baz
           
diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs
new file mode 100644
index 00000000000..75bd7747f4f
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs
@@ -0,0 +1,11 @@
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[link(name = "/absolute-path/liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")]
+unsafe extern "C" {
+    safe fn this_is_a_library_function() -> core::ffi::c_int;
+}
+
+fn main() {
+    println!("{}", this_is_a_library_function())
+}
diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt
new file mode 100644
index 00000000000..d81cc0710eb
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt
@@ -0,0 +1 @@
+42
diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs
new file mode 100644
index 00000000000..d2a9b0477e5
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs
@@ -0,0 +1,20 @@
+//@ only-elf
+//@ ignore-cross-compile: Runs a binary.
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+
+//! Ensure ELF raw-dylib is able to link against a non-existent verbatim absolute path
+//! by embedding the absolute path in the DT_SONAME and passing a different path for
+//! the linker for the stub.
+
+use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc};
+
+fn main() {
+    // We compile the binary without having the library present.
+    // The verbatim library name is an absolute path.
+    rustc().crate_type("bin").input("main.rs").run();
+
+    // FIXME(raw_dylib_elf): Read the NEEDED of the library to ensure it's the absolute path.
+}
diff --git a/tests/run-make/raw-dylib-elf-verbatim/library.c b/tests/run-make/raw-dylib-elf-verbatim/library.c
new file mode 100644
index 00000000000..2e3a95b7ede
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim/library.c
@@ -0,0 +1,3 @@
+int this_is_a_library_function() {
+    return 42;
+}
diff --git a/tests/run-make/raw-dylib-elf-verbatim/main.rs b/tests/run-make/raw-dylib-elf-verbatim/main.rs
new file mode 100644
index 00000000000..044b7400a84
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim/main.rs
@@ -0,0 +1,11 @@
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[link(name = "liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")]
+unsafe extern "C" {
+    safe fn this_is_a_library_function() -> core::ffi::c_int;
+}
+
+fn main() {
+    println!("{}", this_is_a_library_function())
+}
diff --git a/tests/run-make/raw-dylib-elf-verbatim/output.txt b/tests/run-make/raw-dylib-elf-verbatim/output.txt
new file mode 100644
index 00000000000..d81cc0710eb
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim/output.txt
@@ -0,0 +1 @@
+42
diff --git a/tests/run-make/raw-dylib-elf-verbatim/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs
new file mode 100644
index 00000000000..319534b24c8
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs
@@ -0,0 +1,31 @@
+//@ only-elf
+//@ ignore-cross-compile: Runs a binary.
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+
+//! Ensure ELF raw-dylib is able to link against the verbatim versioned library
+//! without it being present, and then be executed against this library.
+
+use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc};
+
+fn main() {
+    // We compile the binary without having the library present.
+    // We also set the rpath to the current directory so we can pick up the library at runtime.
+    rustc()
+        .crate_type("bin")
+        .input("main.rs")
+        .arg(&format!("-Wl,-rpath={}", cwd().display()))
+        .run();
+
+    // Now, *after* building the binary, we build the library...
+    build_native_dynamic_lib("library");
+    // ... rename it to have the versioned library name...
+    rfs::rename("liblibrary.so", "liblibrary.so.1");
+
+    // ... and run with this library, ensuring it was linked correctly at runtime.
+    let output = run("main").stdout_utf8();
+
+    diff().expected_file("output.txt").actual_text("actual", output).run();
+}
diff --git a/tests/run-make/raw-dylib-elf/library.c b/tests/run-make/raw-dylib-elf/library.c
new file mode 100644
index 00000000000..2e3a95b7ede
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf/library.c
@@ -0,0 +1,3 @@
+int this_is_a_library_function() {
+    return 42;
+}
diff --git a/tests/run-make/raw-dylib-elf/main.rs b/tests/run-make/raw-dylib-elf/main.rs
new file mode 100644
index 00000000000..3be944d2951
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf/main.rs
@@ -0,0 +1,11 @@
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[link(name = "library", kind = "raw-dylib")]
+unsafe extern "C" {
+    safe fn this_is_a_library_function() -> core::ffi::c_int;
+}
+
+fn main() {
+    println!("{}", this_is_a_library_function())
+}
diff --git a/tests/run-make/raw-dylib-elf/output.txt b/tests/run-make/raw-dylib-elf/output.txt
new file mode 100644
index 00000000000..d81cc0710eb
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf/output.txt
@@ -0,0 +1 @@
+42
diff --git a/tests/run-make/raw-dylib-elf/rmake.rs b/tests/run-make/raw-dylib-elf/rmake.rs
new file mode 100644
index 00000000000..59f901ac1ed
--- /dev/null
+++ b/tests/run-make/raw-dylib-elf/rmake.rs
@@ -0,0 +1,29 @@
+//@ only-elf
+//@ ignore-cross-compile: Runs a binary.
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+
+//! Ensure ELF raw-dylib is able to link the binary without having the library present,
+//! and then successfully run against the real library.
+
+use run_make_support::{build_native_dynamic_lib, cwd, diff, run, rustc};
+
+fn main() {
+    // We compile the binary without having the library present.
+    // We also set the rpath to the current directory so we can pick up the library at runtime.
+    rustc()
+        .crate_type("bin")
+        .input("main.rs")
+        .arg(&format!("-Wl,-rpath={}", cwd().display()))
+        .run();
+
+    // Now, *after* building the binary, we build the library...
+    build_native_dynamic_lib("library");
+
+    // ... and run with this library, ensuring it was linked correctly at runtime.
+    let output = run("main").stdout_utf8();
+
+    diff().expected_file("output.txt").actual_text("actual", output).run();
+}
diff --git a/tests/run-make/reproducible-build/linker.rs b/tests/run-make/reproducible-build/linker.rs
index ab3b4049cc3..2f57d9f9be9 100644
--- a/tests/run-make/reproducible-build/linker.rs
+++ b/tests/run-make/reproducible-build/linker.rs
@@ -17,6 +17,8 @@ fn main() {
     for arg in env::args().skip(1) {
         let path = Path::new(&arg);
         if !path.is_file() {
+            // This directory is produced during linking in a temporary directory (ELF only).
+            let arg = if arg.ends_with("/raw-dylibs") { "/raw-dylibs" } else { &*arg };
             out.push_str(&arg);
             out.push_str("\n");
             continue;
diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout
index 382b1c96682..c8ea09ee2c8 100644
--- a/tests/run-make/rustc-help/help-v.stdout
+++ b/tests/run-make/rustc-help/help-v.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout
index 08bb7f85098..434e71e901e 100644
--- a/tests/run-make/rustc-help/help.stdout
+++ b/tests/run-make/rustc-help/help.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index c1b246e849c..01f470f6e16 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -153,7 +153,7 @@ Options:
         --generate-redirect-map 
                         Generate JSON file at the top level instead of
                         generating HTML redirection files
-        --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
+        --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]
                         Comma separated list of types of output for rustdoc to
                         emit
         --no-run        Compile doctests without running them
diff --git a/tests/run-make/rustdoc-default-output/rmake.rs b/tests/run-make/rustdoc-default-output/rmake.rs
index 06720445a35..5f9c501e528 100644
--- a/tests/run-make/rustdoc-default-output/rmake.rs
+++ b/tests/run-make/rustdoc-default-output/rmake.rs
@@ -3,10 +3,10 @@
 // ensures the output of rustdoc's help menu is as expected.
 // See https://github.com/rust-lang/rust/issues/88756
 
-use run_make_support::{bare_rustdoc, diff};
+use run_make_support::{diff, rustdoc};
 
 fn main() {
-    let out = bare_rustdoc().run().stdout_utf8();
+    let out = rustdoc().run().stdout_utf8();
     diff()
         .expected_file("output-default.stdout")
         .actual_text("actual", out)
diff --git a/tests/run-make/rustdoc-dep-info/bar.rs b/tests/run-make/rustdoc-dep-info/bar.rs
new file mode 100644
index 00000000000..76b8dcd05c8
--- /dev/null
+++ b/tests/run-make/rustdoc-dep-info/bar.rs
@@ -0,0 +1 @@
+include!("foo.rs");
diff --git a/tests/run-make/rustdoc-dep-info/doc.md b/tests/run-make/rustdoc-dep-info/doc.md
new file mode 100644
index 00000000000..6a4238fc8b6
--- /dev/null
+++ b/tests/run-make/rustdoc-dep-info/doc.md
@@ -0,0 +1 @@
+blablabla
diff --git a/tests/run-make/rustdoc-dep-info/foo.rs b/tests/run-make/rustdoc-dep-info/foo.rs
new file mode 100644
index 00000000000..b76b4321d62
--- /dev/null
+++ b/tests/run-make/rustdoc-dep-info/foo.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/tests/run-make/rustdoc-dep-info/lib.rs b/tests/run-make/rustdoc-dep-info/lib.rs
new file mode 100644
index 00000000000..1f003f79b1f
--- /dev/null
+++ b/tests/run-make/rustdoc-dep-info/lib.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+#[cfg_attr(doc, doc = include_str!("doc.md"))]
+pub struct Bar;
+
+mod bar;
diff --git a/tests/run-make/rustdoc-dep-info/rmake.rs b/tests/run-make/rustdoc-dep-info/rmake.rs
new file mode 100644
index 00000000000..6902bfc21ca
--- /dev/null
+++ b/tests/run-make/rustdoc-dep-info/rmake.rs
@@ -0,0 +1,21 @@
+// This is a simple smoke test for rustdoc's `--emit dep-info` feature. It prints out
+// information about dependencies in a Makefile-compatible format, as a `.d` file.
+
+use run_make_support::assertion_helpers::assert_contains;
+use run_make_support::{path, rfs, rustdoc};
+
+fn main() {
+    // We're only emitting dep info, so we shouldn't be running static analysis to
+    // figure out that this program is erroneous.
+    rustdoc().input("lib.rs").arg("-Zunstable-options").emit("dep-info").run();
+
+    let content = rfs::read_to_string("foo.d");
+    assert_contains(&content, "lib.rs:");
+    assert_contains(&content, "foo.rs:");
+    assert_contains(&content, "bar.rs:");
+    assert_contains(&content, "doc.md:");
+
+    // Now we check that we can provide a file name to the `dep-info` argument.
+    rustdoc().input("lib.rs").arg("-Zunstable-options").emit("dep-info=bla.d").run();
+    assert!(path("bla.d").exists());
+}
diff --git a/tests/run-make/tools.mk b/tests/run-make/tools.mk
deleted file mode 100644
index b1e872a202a..00000000000
--- a/tests/run-make/tools.mk
+++ /dev/null
@@ -1,209 +0,0 @@
-# These deliberately use `=` and not `:=` so that client makefiles can
-# augment HOST_RPATH_DIR / TARGET_RPATH_DIR.
-HOST_RPATH_ENV = \
-    $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(HOST_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))"
-TARGET_RPATH_ENV = \
-    $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(TARGET_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))"
-
-RUSTC_ORIGINAL := $(RUSTC)
-BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
-BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
-RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) -Ainternal_features
-RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR)
-ifdef RUSTC_LINKER
-RUSTC := $(RUSTC) -Clinker='$(RUSTC_LINKER)'
-RUSTDOC := $(RUSTDOC) -Clinker='$(RUSTC_LINKER)'
-endif
-#CC := $(CC) -L $(TMPDIR)
-HTMLDOCCK := '$(PYTHON)' '$(S)/src/etc/htmldocck.py'
-CGREP := "$(S)/src/etc/cat-and-grep.sh"
-
-# diff with common flags for multi-platform diffs against text output
-DIFF := diff -u --strip-trailing-cr
-
-# With RUSTC_TEST_OP you can elegantly support blessing of run-make tests. Do
-# like this in a Makefile recipe:
-#
-#   "$(TMPDIR)"/your-test > "$(TMPDIR)"/your-test.run.stdout
-#   $(RUSTC_TEST_OP) "$(TMPDIR)"/your-test.run.stdout your-test.run.stdout
-#
-# When running the test normally with
-#
-#   ./x test tests/run-make/your-test
-#
-# the actual output will be diffed against the expected output. When running in
-# bless-mode with
-#
-#   ./x test --bless tests/run-make/your-test
-#
-# the actual output will be blessed as the expected output.
-ifdef RUSTC_BLESS_TEST
-    RUSTC_TEST_OP = cp
-else
-    RUSTC_TEST_OP = $(DIFF)
-endif
-
-# Some of the Rust CI platforms use `/bin/dash` to run `shell` script in
-# Makefiles. Other platforms, including many developer platforms, default to
-# `/bin/bash`. (In many cases, `make` is actually using `/bin/sh`, but `sh`
-# is configured to execute one or the other shell binary). `dash` features
-# support only a small subset of `bash` features, so `dash` can be thought of as
-# the lowest common denominator, and tests should be validated against `dash`
-# whenever possible. Most developer platforms include `/bin/dash`, but to ensure
-# tests still work when `/bin/dash`, if not available, this `SHELL` override is
-# conditional:
-ifndef IS_WINDOWS # dash interprets backslashes in executable paths incorrectly
-ifneq (,$(wildcard /bin/dash))
-SHELL := /bin/dash
-endif
-endif
-
-# This is the name of the binary we will generate and run; use this
-# e.g. for `$(CC) -o $(RUN_BINFILE)`.
-RUN_BINFILE = $(TMPDIR)/$(1)
-
-# Invoke the generated binary on the remote machine if compiletest was
-# configured to use a remote test device, otherwise run it on the current host.
-ifdef REMOTE_TEST_CLIENT
-# FIXME: if a test requires additional files, this will need to be changed to
-# also push them (by changing the 0 to the number of additional files, and
-# providing the path of the additional files as the last arguments).
-EXECUTE = $(REMOTE_TEST_CLIENT) run 0 $(RUN_BINFILE)
-else
-EXECUTE = $(RUN_BINFILE)
-endif
-
-# RUN and FAIL are basic way we will invoke the generated binary.  On
-# non-windows platforms, they set the LD_LIBRARY_PATH environment
-# variable before running the binary.
-
-RLIB_GLOB = lib$(1)*.rlib
-BIN = $(1)
-
-UNAME = $(shell uname)
-
-ifeq ($(UNAME),Darwin)
-RUN = $(TARGET_RPATH_ENV) $(EXECUTE)
-FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0
-DYLIB_GLOB = lib$(1)*.dylib
-DYLIB = $(TMPDIR)/lib$(1).dylib
-STATICLIB = $(TMPDIR)/lib$(1).a
-STATICLIB_GLOB = lib$(1)*.a
-else
-ifdef IS_WINDOWS
-RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE)
-FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE) && exit 1 || exit 0
-DYLIB_GLOB = $(1)*.dll
-DYLIB = $(TMPDIR)/$(1).dll
-ifdef IS_MSVC
-STATICLIB = $(TMPDIR)/$(1).lib
-STATICLIB_GLOB = $(1)*.lib
-else
-IMPLIB = $(TMPDIR)/lib$(1).dll.a
-STATICLIB = $(TMPDIR)/lib$(1).a
-STATICLIB_GLOB = lib$(1)*.a
-endif
-BIN = $(1).exe
-LLVM_FILECHECK := $(shell cygpath -u "$(LLVM_FILECHECK)")
-else
-RUN = $(TARGET_RPATH_ENV) $(EXECUTE)
-FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0
-DYLIB_GLOB = lib$(1)*.so
-DYLIB = $(TMPDIR)/lib$(1).so
-STATICLIB = $(TMPDIR)/lib$(1).a
-STATICLIB_GLOB = lib$(1)*.a
-endif
-endif
-
-ifdef IS_MSVC
-COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
-COMPILE_OBJ_CXX = $(CXX) -EHs -c -Fo:`cygpath -w $(1)` $(2)
-NATIVE_STATICLIB_FILE = $(1).lib
-NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
-OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
-	-Fo:`cygpath -w $(TMPDIR)/$(1).obj`
-else
-COMPILE_OBJ = $(CC) -v -c -o $(1) $(2)
-COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
-NATIVE_STATICLIB_FILE = lib$(1).a
-NATIVE_STATICLIB = $(call STATICLIB,$(1))
-OUT_EXE=-o $(TMPDIR)/$(1)
-endif
-
-
-# Extra flags needed to compile a working executable with the standard library
-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
-	EXTRACXXFLAGS := -lstdc++
-	# 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
-	# instances of the DW2 unwinding implementation. This is a problem on
-	# i686-pc-windows-gnu because each module (DLL/EXE) needs to register its
-	# unwind information with the unwinding implementation, and libstdc++'s
-	# __cxa_throw won't see the unwinding info we registered with our statically
-	# linked libgcc.
-	#
-	# Now, simply statically linking libstdc++ would fix this problem, except
-	# that it is compiled with the expectation that pthreads is dynamically
-	# linked as a DLL and will fail to link with a statically linked libpthread.
-	#
-	# So we end up with the following hack: we link use static:-bundle to only
-	# link the parts of libstdc++ that we actually use, which doesn't include
-	# the dependency on the pthreads DLL.
-	EXTRARSCXXFLAGS := -l static:-bundle=stdc++
-endif
-else
-ifeq ($(UNAME),Darwin)
-	EXTRACFLAGS := -lresolv
-	EXTRACXXFLAGS := -lc++
-	EXTRARSCXXFLAGS := -lc++
-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
-	RUSTC := $(RUSTC) -C linker="$(word 1,$(CC:ccache=))"
-else
-	EXTRACFLAGS := -lm -lrt -ldl -lpthread
-	EXTRACXXFLAGS := -lstdc++
-	EXTRARSCXXFLAGS := -lstdc++
-endif
-endif
-endif
-endif
-endif
-
-REMOVE_DYLIBS     = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1))
-REMOVE_RLIBS      = rm $(TMPDIR)/$(call RLIB_GLOB,$(1))
-
-%.a: %.o
-	$(AR) crus $@ $<
-ifdef IS_MSVC
-%.lib: lib%.o
-	$(MSVC_LIB) -out:`cygpath -w $@` $<
-else
-%.lib: lib%.o
-	$(AR) crus $@ $<
-endif
-%.dylib: %.o
-	$(CC) -dynamiclib -Wl,-dylib -o $@ $<
-%.so: %.o
-	$(CC) -o $@ $< -shared
-
-ifdef IS_MSVC
-%.dll: lib%.o
-	$(CC) $< -link -dll -out:`cygpath -w $@`
-else
-%.dll: lib%.o
-	$(CC) -o $@ $< -shared -Wl,--out-implib=$@.a
-endif
-
-$(TMPDIR)/lib%.o: %.c
-	$(call COMPILE_OBJ,$@,$<)
diff --git a/tests/run-make/version-verbose-commit-hash/rmake.rs b/tests/run-make/version-verbose-commit-hash/rmake.rs
index 733c0e2cdb1..ae8dda38ab4 100644
--- a/tests/run-make/version-verbose-commit-hash/rmake.rs
+++ b/tests/run-make/version-verbose-commit-hash/rmake.rs
@@ -5,13 +5,13 @@
 
 //@ needs-git-hash
 
-use run_make_support::{bare_rustc, bare_rustdoc, regex};
+use run_make_support::{bare_rustc, regex, rustdoc};
 
 fn main() {
     let out_rustc =
         bare_rustc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
     let out_rustdoc =
-        bare_rustdoc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
+        rustdoc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
     let re =
         regex::Regex::new(r#"commit-hash: [0-9a-f]{40}\ncommit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"#)
             .unwrap();
diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs
index a023c9fbf6e..7508490d666 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(repr128)]
 #![allow(incomplete_features)]
 
diff --git a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
index f16a74d638b..6f66495bed2 100644
--- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
+++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #[repr(u32)]
 pub enum Foo {
     //@ is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"'
diff --git a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
index 522545d34d0..8e7985f07f4 100644
--- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
+++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 pub enum Foo {
     //@ is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}'
     Has = 0,
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index 24d5f5b08c2..82437f5ef03 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #[repr(i32)]
 //@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(SignedInt(I32))])\")]\n"]'
 pub enum Foo {
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index a50ae8b9189..25bba07e8f7 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #[repr(u32)]
 //@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(UnsignedInt(U32))])\")]\n"]'
 pub enum Foo {
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index 2e0fb3101a3..517a53828b7 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 pub enum Foo {
     //@ set Unit = "$.index[*][?(@.name=='Unit')].id"
     //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs
index 03fbb3b795d..13a967bd35e 100644
--- a/tests/rustdoc-json/fn_pointer/abi.rs
+++ b/tests/rustdoc-json/fn_pointer/abi.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #![feature(abi_vectorcall)]
 
 //@ is "$.index[*][?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\"
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index 7d64e490a22..c974b472297 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"'
 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index 6f03cf58522..398e31f72db 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false
 //@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false
 //@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false
diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs
index 2f6413cee6f..68957f79952 100644
--- a/tests/rustdoc-json/fns/abi.rs
+++ b/tests/rustdoc-json/fns/abi.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #![feature(abi_vectorcall)]
 
 //@ is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index ff88fa99c61..ddfd4ccf90d 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -1,5 +1,4 @@
 //@ edition:2021
-// ignore-tidy-linelength
 
 // Regression test for <https://github.com/rust-lang/rust/issues/101199>
 
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index b5412446ab4..6a7124976f8 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index 2f23801fc3f..90e17525c44 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2
 
 //@ set foo = "$.index[*][?(@.name=='Foo')].id"
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index f2064fd1e93..b953094b5de 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ set wham_id = "$.index[*][?(@.name=='Wham')].id"
 pub trait Wham {}
 
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index fdf605e9287..d1172b35fda 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 pub trait Display {}
 
 pub trait LendingIterator {
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
index 14ea2950769..fc12fc87e8d 100644
--- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(impl_trait_in_assoc_type)]
 
 pub struct AlwaysTrue;
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 8ac60be0fef..2d4e098d696 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name"  \"\'a\"
 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index 99d14296f99..257e43985ac 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" []
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\"
diff --git a/tests/rustdoc-json/lifetime/outlives_in_param.rs b/tests/rustdoc-json/lifetime/outlives_in_param.rs
index 3eee6d9ea46..55ff5250541 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_param.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_param.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ count '$.index[*][?(@.name=="outlives")].inner.function.generics.params[*]' 2
 //@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\"
 //@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' []
diff --git a/tests/rustdoc-json/lifetime/outlives_in_where.rs b/tests/rustdoc-json/lifetime/outlives_in_where.rs
index a8f88be01da..5158ff118a0 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_where.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_where.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ is '$.index[*][?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]'
 pub fn on_lifetimes<'a, 'b, 'c, 'all>()
 where
diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs
index 6d33dfca373..dac02a6ce3c 100644
--- a/tests/rustdoc-json/methods/abi.rs
+++ b/tests/rustdoc-json/methods/abi.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #![feature(abi_vectorcall)]
 
 //@ has "$.index[*][?(@.name=='Foo')]"
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index 8443141fecd..7c518a8f5a7 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 #![feature(non_lifetime_binders)]
 #![allow(incomplete_features)]
 
diff --git a/tests/rustdoc-json/path_name.rs b/tests/rustdoc-json/path_name.rs
index 67843dfc8ff..a1b3ae294fa 100644
--- a/tests/rustdoc-json/path_name.rs
+++ b/tests/rustdoc-json/path_name.rs
@@ -3,7 +3,6 @@
 // See https://github.com/rust-lang/rust/issues/135600
 // and https://github.com/rust-lang/rust/pull/134880#issuecomment-2596386111
 //
-// ignore-tidy-linelength
 //@ aux-build: defines_and_reexports.rs
 extern crate defines_and_reexports;
 
diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
index 512c741798b..4debd395496 100644
--- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
+++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
@@ -1,6 +1,5 @@
 // Regression Test for https://github.com/rust-lang/rust/issues/110138
 //@ aux-build: enum_with_discriminant.rs
-// ignore-tidy-linelength
 
 #[doc(inline)]
 pub extern crate enum_with_discriminant;
diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
index 6e9b5044816..4efacd283ef 100644
--- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
+++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
@@ -2,7 +2,5 @@
 
 #![crate_name = "export_extern_crate_as_self"]
 
-// ignore-tidy-linelength
-
 //@ is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\"
 pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index 87b97e65c0a..fdf8cda103b 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -1,5 +1,4 @@
 //@ aux-build:pub-struct.rs
-// ignore-tidy-linelength
 
 // Test for the ICE in https://github.com/rust-lang/rust/issues/83057
 // An external type re-exported with different attributes shouldn't cause an error
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index 1ed54f15fdc..049100d7f49 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // Test for the ICE in https://github.com/rust-lang/rust/issues/83720
 // A pub-in-private type re-exported under two different names shouldn't cause an error
 
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index 27e2827d08d..f313171afa5 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // Regression test for <https://github.com/rust-lang/rust/issues/97432>.
 
 #![no_std]
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index bfcbed89040..214fda14aca 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -1,5 +1,4 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/96161>.
-// ignore-tidy-linelength
 
 mod secret {
     //@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id"
diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs
index d38fdf1cd1c..9e0265da8e2 100644
--- a/tests/rustdoc-json/statics/extern.rs
+++ b/tests/rustdoc-json/statics/extern.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 //@ edition: 2021
 
 extern "C" {
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index 7202ab9af9c..fe99292456d 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
 //@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
 //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs
index 3ae5fad8acc..d9ef256b106 100644
--- a/tests/rustdoc-json/trait_alias.rs
+++ b/tests/rustdoc-json/trait_alias.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(trait_alias)]
 
 //@ set StrLike = "$.index[*][?(@.name=='StrLike')].id"
diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs
index d31b6ca4ad8..ce0642278e0 100644
--- a/tests/rustdoc-json/traits/private_supertrait.rs
+++ b/tests/rustdoc-json/traits/private_supertrait.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ !has "$.index[*][?(@.name == 'sealed')]"
 mod sealed {
     //@ set sealed_id = "$.index[*][?(@.name=='Sealed')].id"
diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs
index 060bc37f2d5..efd9efd556f 100644
--- a/tests/rustdoc-json/traits/self.rs
+++ b/tests/rustdoc-json/traits/self.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 pub struct Foo;
 
 // Check that Self is represented uniformly between inherent impls, trait impls,
diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs
index e8fe82ab9cd..4b6199d4b26 100644
--- a/tests/rustdoc-json/traits/supertrait.rs
+++ b/tests/rustdoc-json/traits/supertrait.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ set loud_id = "$.index[*][?(@.name=='Loud')].id"
 pub trait Loud {}
 
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index 17c83ddc353..137b8947e23 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -1,5 +1,4 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/104923>
-// ignore-tidy-linelength
 
 #![feature(trait_alias)]
 
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index f990a2cb53a..d8686d4e2fb 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 use std::fmt::Debug;
 
 //@ count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index 7fa12dad54e..aaa716bf11f 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ has "$.index[*][?(@.name=='GenericFn')].inner.type_alias"
 
 //@ ismany "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\"
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 7eaa299af5c..2d2ce9cd103 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ set result = "$.index[*][?(@.name=='Result')].id"
 pub enum Result<T, E> {
     Ok(T),
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index e71d9fc1e1e..08b35b90a2b 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 //@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}'
 //@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
 pub fn genfn<F>(f: F)
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
index b8ce11fc6e1..e26f8f7c651 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index cb008291b72..22c9c9c1149 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index e73e86d5817..501694dce8b 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
diff --git a/tests/rustdoc-ui/issues/issue-79494.rs b/tests/rustdoc-ui/issues/issue-79494.rs
index 7a1890c4429..28ef82dac0f 100644
--- a/tests/rustdoc-ui/issues/issue-79494.rs
+++ b/tests/rustdoc-ui/issues/issue-79494.rs
@@ -2,4 +2,4 @@
 
 #![feature(const_transmute)]
 
-const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; //~ ERROR cannot transmute between types of different sizes, or dependently-sized types
+pub const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; //~ ERROR cannot transmute between types of different sizes, or dependently-sized types
diff --git a/tests/rustdoc-ui/issues/issue-79494.stderr b/tests/rustdoc-ui/issues/issue-79494.stderr
index abcd69d3aae..20e568d8eab 100644
--- a/tests/rustdoc-ui/issues/issue-79494.stderr
+++ b/tests/rustdoc-ui/issues/issue-79494.stderr
@@ -1,8 +1,8 @@
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/issue-79494.rs:5:29
+  --> $DIR/issue-79494.rs:5:33
    |
-LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
-   |                             ^^^^^^^^^^^^^^^^^^^
+LL | pub const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
+   |                                 ^^^^^^^^^^^^^^^^^^^
    |
    = note: source type: `usize` (64 bits)
    = note: target type: `&[u8]` (128 bits)
diff --git a/tests/rustdoc-ui/target-feature-stability.rs b/tests/rustdoc-ui/target-feature-stability.rs
new file mode 100644
index 00000000000..17fa3ccfe3e
--- /dev/null
+++ b/tests/rustdoc-ui/target-feature-stability.rs
@@ -0,0 +1,28 @@
+//! This is a regression test for <https://github.com/rust-lang/rust/issues/137366>, ensuring
+//! that we can use the `neon` target feature on ARM32 targets in rustdoc despite there
+//! being a "forbidden" feature of the same name for aarch64, and rustdoc merging the
+//! target features of all targets.
+//@ check-pass
+//@ revisions: arm aarch64
+//@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@[arm] needs-llvm-components: arm
+//@[aarch64] compile-flags: --target aarch64-unknown-none-softfloat
+//@[aarch64] needs-llvm-components: aarch64
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![feature(arm_target_feature)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+// `fp-armv8` is "forbidden" on aarch64 as we tie it to `neon`.
+#[target_feature(enable = "fp-armv8")]
+pub fn fun1() {}
+
+// This would usually be rejected as it changes the ABI.
+// But we disable that check in rustdoc since we are building "for all targets" and the
+// check can't really handle that.
+#[target_feature(enable = "soft-float")]
+pub fn fun2() {}
diff --git a/tests/rustdoc-ui/track-diagnostics.rs b/tests/rustdoc-ui/track-diagnostics.rs
index 5c950a11082..27781f47e0d 100644
--- a/tests/rustdoc-ui/track-diagnostics.rs
+++ b/tests/rustdoc-ui/track-diagnostics.rs
@@ -7,4 +7,5 @@
 
 struct A;
 struct B;
-const S: A = B;
+
+pub const S: A = B;
diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr
index 3d17570a7a2..fb0d7b86644 100644
--- a/tests/rustdoc-ui/track-diagnostics.stderr
+++ b/tests/rustdoc-ui/track-diagnostics.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/track-diagnostics.rs:LL:CC
    |
-LL | const S: A = B;
-   |              ^ expected `A`, found `B`
+LL | pub const S: A = B;
+   |                  ^ expected `A`, found `B`
 -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
 
 error: aborting due to 1 previous error
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout
index 4d58fd503d0..5cf39ca3165 100644
--- a/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout
@@ -1,4 +1,4 @@
-$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/libhotplug.rlib: $DIR/hotplug.rs $TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so
+$TEST_BUILD_DIR/libhotplug.rlib: $DIR/hotplug.rs $TEST_BUILD_DIR/auxiliary/libthe_backend.so
 
 $DIR/hotplug.rs:
-$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so:
+$TEST_BUILD_DIR/auxiliary/libthe_backend.so:
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout
index 48b7534d8fa..717439f14e1 100644
--- a/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout
@@ -1,3 +1,3 @@
-$TEST_BUILD_DIR/codegen-backend/hotplug.dep/libhotplug.rlib: $DIR/hotplug.rs
+$TEST_BUILD_DIR/libhotplug.rlib: $DIR/hotplug.rs
 
 $DIR/hotplug.rs:
diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
index 9fa4929d68e..9d71697178e 100644
--- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
+++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
@@ -18,9 +18,11 @@ extern crate rustc_interface;
 extern crate stable_mir;
 
 use rustc_smir::rustc_internal;
-use stable_mir::ty::{RigidTy, TyKind, Ty, };
-use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location,
-                                                                            PlaceContext}};
+use stable_mir::mir::{
+    Body, FieldIdx, MirVisitor, Place, ProjectionElem,
+    visit::{Location, PlaceContext},
+};
+use stable_mir::ty::{RigidTy, Ty, TyKind};
 use std::io::Write;
 use std::ops::ControlFlow;
 
@@ -29,8 +31,8 @@ const CRATE_NAME: &str = "input";
 /// This function uses the Stable MIR APIs to get information about the test crate.
 fn test_stable_mir() -> ControlFlow<()> {
     let main_fn = stable_mir::entry_fn();
-    let body = main_fn.unwrap().body();
-    let mut visitor = PlaceVisitor{ body: &body, tested: false};
+    let body = main_fn.unwrap().expect_body();
+    let mut visitor = PlaceVisitor { body: &body, tested: false };
     visitor.visit_body(&body);
     assert!(visitor.tested);
     ControlFlow::Continue(())
diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs
index 7f0e9b50335..4d2d7e26276 100644
--- a/tests/ui-fulldeps/stable-mir/crate-info.rs
+++ b/tests/ui-fulldeps/stable-mir/crate-info.rs
@@ -45,7 +45,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     assert!(stable_mir::find_crates("std").len() == 1);
 
     let bar = get_item(&items, (DefKind::Fn, "bar")).unwrap();
-    let body = bar.body();
+    let body = bar.expect_body();
     assert_eq!(body.locals().len(), 2);
     assert_eq!(body.blocks.len(), 1);
     let block = &body.blocks[0];
@@ -60,7 +60,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     }
 
     let foo_bar = get_item(&items, (DefKind::Fn, "foo_bar")).unwrap();
-    let body = foo_bar.body();
+    let body = foo_bar.expect_body();
     assert_eq!(body.locals().len(), 5);
     assert_eq!(body.blocks.len(), 4);
     let block = &body.blocks[0];
@@ -70,7 +70,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     }
 
     let types = get_item(&items, (DefKind::Fn, "types")).unwrap();
-    let body = types.body();
+    let body = types.expect_body();
     assert_eq!(body.locals().len(), 6);
     assert_matches!(
         body.locals()[0].ty.kind(),
@@ -100,7 +100,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     );
 
     let drop = get_item(&items, (DefKind::Fn, "drop")).unwrap();
-    let body = drop.body();
+    let body = drop.expect_body();
     assert_eq!(body.blocks.len(), 2);
     let block = &body.blocks[0];
     match &block.terminator.kind {
@@ -109,7 +109,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     }
 
     let assert = get_item(&items, (DefKind::Fn, "assert")).unwrap();
-    let body = assert.body();
+    let body = assert.expect_body();
     assert_eq!(body.blocks.len(), 2);
     let block = &body.blocks[0];
     match &block.terminator.kind {
@@ -123,7 +123,8 @@ fn test_stable_mir() -> ControlFlow<()> {
         match &block.terminator.kind {
             stable_mir::mir::TerminatorKind::Call { func, .. } => {
                 let TyKind::RigidTy(ty) = func.ty(&body.locals()).unwrap().kind() else {
-                    unreachable!() };
+                    unreachable!()
+                };
                 let RigidTy::FnDef(def, args) = ty else { unreachable!() };
                 let next_func = Instance::resolve(def, &args).unwrap();
                 match next_func.body().unwrap().locals()[1].ty.kind() {
@@ -138,10 +139,10 @@ fn test_stable_mir() -> ControlFlow<()> {
 
     let foo_const = get_item(&items, (DefKind::Const, "FOO")).unwrap();
     // Ensure we don't panic trying to get the body of a constant.
-    foo_const.body();
+    foo_const.expect_body();
 
     let locals_fn = get_item(&items, (DefKind::Fn, "locals")).unwrap();
-    let body = locals_fn.body();
+    let body = locals_fn.expect_body();
     assert_eq!(body.locals().len(), 4);
     assert_matches!(
         body.ret_local().ty.kind(),
@@ -172,8 +173,10 @@ fn get_item<'a>(
     item: (DefKind, &str),
 ) -> Option<&'a stable_mir::CrateItem> {
     items.iter().find(|crate_item| {
-        matches!((item.0, crate_item.kind()), (DefKind::Fn, ItemKind::Fn) | (DefKind::Const,
-            ItemKind::Const)) && crate_item.name() == item.1
+        matches!(
+            (item.0, crate_item.kind()),
+            (DefKind::Fn, ItemKind::Fn) | (DefKind::Const, ItemKind::Const)
+        ) && crate_item.name() == item.1
     })
 }
 
diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs
index 3cc71247e67..6f82eba61fc 100644
--- a/tests/ui-fulldeps/stable-mir/projections.rs
+++ b/tests/ui-fulldeps/stable-mir/projections.rs
@@ -18,10 +18,10 @@ extern crate rustc_interface;
 extern crate stable_mir;
 
 use rustc_smir::rustc_internal;
+use stable_mir::ItemKind;
 use stable_mir::crate_def::CrateDef;
 use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
 use stable_mir::ty::{RigidTy, TyKind, UintTy};
-use stable_mir::ItemKind;
 use std::assert_matches::assert_matches;
 use std::io::Write;
 use std::ops::ControlFlow;
@@ -31,7 +31,7 @@ const CRATE_NAME: &str = "input";
 /// Tests projections within Place objects
 fn test_place_projections() -> ControlFlow<()> {
     let items = stable_mir::all_local_items();
-    let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body();
+    let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().expect_body();
     assert_eq!(body.blocks.len(), 4);
     // The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
     // `s` is passed as a reference argument, and a field access for field `c`.
@@ -53,7 +53,7 @@ fn test_place_projections() -> ControlFlow<()> {
                     );
                     let ty = place.ty(body.locals()).unwrap();
                     assert_matches!(ty.kind().rigid(), Some(RigidTy::Ref(..)));
-                },
+                }
                 other => panic!(
                     "Unable to match against expected rvalue projection. Expected the projection \
                      for `s.c`, which is a Deref and u8 Field. Got: {:?}",
@@ -137,9 +137,7 @@ fn get_item<'a>(
     items: &'a stable_mir::CrateItems,
     item: (ItemKind, &str),
 ) -> Option<&'a stable_mir::CrateItem> {
-    items.iter().find(|crate_item| {
-        crate_item.kind() == item.0 && crate_item.name() == item.1
-    })
+    items.iter().find(|crate_item| crate_item.kind() == item.0 && crate_item.name() == item.1)
 }
 
 /// This test will generate and analyze a dummy crate using the stable mir.
diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs
index 453e5372de4..f9972dc27e3 100644
--- a/tests/ui-fulldeps/stable-mir/smir_internal.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs
@@ -26,7 +26,7 @@ const CRATE_NAME: &str = "input";
 
 fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let main_fn = stable_mir::entry_fn().unwrap();
-    let body = main_fn.body();
+    let body = main_fn.expect_body();
     let orig_ty = body.locals()[0].ty;
     let rustc_ty = rustc_internal::internal(tcx, &orig_ty);
     assert!(rustc_ty.is_unit());
diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs
index 2c74276d550..9b3638a9f2f 100644
--- a/tests/ui-fulldeps/stable-mir/smir_serde.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs
@@ -14,33 +14,29 @@ extern crate rustc_smir;
 extern crate rustc_driver;
 extern crate rustc_interface;
 extern crate rustc_middle;
-extern crate stable_mir;
 extern crate serde;
 extern crate serde_json;
+extern crate stable_mir;
 
 use rustc_middle::ty::TyCtxt;
 use rustc_smir::rustc_internal;
+use serde_json::to_string;
 use stable_mir::mir::Body;
-use std::io::{Write, BufWriter};
+use std::io::{BufWriter, Write};
 use std::ops::ControlFlow;
-use serde_json::to_string;
-
 
 const CRATE_NAME: &str = "input";
 
 fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let path = "output.json";
-    let mut writer = BufWriter::new(std::fs::File::create(path)
-        .expect("Failed to create path"));
+    let mut writer = BufWriter::new(std::fs::File::create(path).expect("Failed to create path"));
     let local_crate = stable_mir::local_crate();
-    let items: Vec<Body> = stable_mir::all_local_items()
-        .iter()
-        .map(|item| { item.body() })
-        .collect();
-    let crate_data = ( local_crate.name, items );
-    writer.write_all(to_string(&crate_data)
-        .expect("serde_json failed")
-        .as_bytes()).expect("JSON serialization failed");
+    let items: Vec<Body> =
+        stable_mir::all_local_items().iter().map(|item| item.expect_body()).collect();
+    let crate_data = (local_crate.name, items);
+    writer
+        .write_all(to_string(&crate_data).expect("serde_json failed").as_bytes())
+        .expect("JSON serialization failed");
     ControlFlow::Continue(())
 }
 
diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
index 0a6415d490e..cffb41742b4 100644
--- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
@@ -16,10 +16,10 @@ extern crate rustc_driver;
 extern crate rustc_interface;
 extern crate stable_mir;
 
-use std::collections::HashSet;
 use rustc_smir::rustc_internal;
-use stable_mir::*;
 use stable_mir::mir::MirVisitor;
+use stable_mir::*;
+use std::collections::HashSet;
 use std::io::Write;
 use std::ops::ControlFlow;
 
@@ -27,7 +27,7 @@ const CRATE_NAME: &str = "input";
 
 fn test_visitor() -> ControlFlow<()> {
     let main_fn = stable_mir::entry_fn();
-    let main_body = main_fn.unwrap().body();
+    let main_body = main_fn.unwrap().expect_body();
     let main_visitor = TestVisitor::collect(&main_body);
     assert!(main_visitor.ret_val.is_some());
     assert!(main_visitor.args.is_empty());
@@ -51,7 +51,7 @@ struct TestVisitor<'a> {
     pub tys: HashSet<ty::Ty>,
     pub ret_val: Option<mir::LocalDecl>,
     pub args: Vec<mir::LocalDecl>,
-    pub calls: Vec<mir::mono::Instance>
+    pub calls: Vec<mir::mono::Instance>,
 }
 
 impl<'a> TestVisitor<'a> {
@@ -90,8 +90,8 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> {
     fn visit_terminator(&mut self, term: &mir::Terminator, location: mir::visit::Location) {
         if let mir::TerminatorKind::Call { func, .. } = &term.kind {
             let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).unwrap().kind() else {
-                unreachable!
-            () };
+                unreachable!()
+            };
             let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() };
             self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap());
         }
diff --git a/tests/ui/abi/rust-cold-works-with-rustic-args.rs b/tests/ui/abi/rust-cold-works-with-rustic-args.rs
new file mode 100644
index 00000000000..57027364699
--- /dev/null
+++ b/tests/ui/abi/rust-cold-works-with-rustic-args.rs
@@ -0,0 +1,6 @@
+//@build-pass
+//@compile-flags: -Clink-dead-code=true --crate-type lib
+// We used to not handle all "rustic" ABIs in a (relatively) uniform way,
+// so we failed to fix up arguments for actually passing through the ABI...
+#![feature(rust_cold_cc)]
+pub extern "rust-cold" fn foo(_: [usize; 3]) {}
diff --git a/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs
index 376630b8d33..7d21307e1b2 100644
--- a/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs
+++ b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs
@@ -1,9 +1,10 @@
 //@ check-pass
 #![allow(improper_ctypes_definitions)]
-#![feature(unsized_tuple_coercion)]
 #![feature(unsized_fn_params)]
 #![crate_type = "lib"]
 
+struct Fat<T: ?Sized>(T);
+
 // Check that computing the fn abi for `bad`, with a external ABI fn ptr that is not FFI-safe, does
 // not ICE.
 
@@ -19,12 +20,12 @@ pub extern "C" fn declare_bad(_x: str) {}
 pub extern "system" fn declare_more_bad(f: dyn FnOnce()) {
 }
 
-fn make_bad() -> extern "C" fn(([u8],)) {
+fn make_bad() -> extern "C" fn(Fat<[u8]>) {
     todo!()
 }
 
 pub fn call_bad() {
     let f = make_bad();
-    let slice: Box<([u8],)> = Box::new(([1; 8],));
+    let slice: Box<Fat<[u8]>> = Box::new(Fat([1; 8]));
     f(*slice);
 }
diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr
index 01f071f1f31..c11cc4e2d52 100644
--- a/tests/ui/abi/unsupported.aarch64.stderr
+++ b/tests/ui/abi/unsupported.aarch64.stderr
@@ -206,3 +206,113 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 19 previous errors; 10 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "aapcs" is not supported on this target
+  --> $DIR/unsupported.rs:51:17
+   |
+LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "riscv-interrupt-m" is not supported on this target
+  --> $DIR/unsupported.rs:96:17
+   |
+LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "x86-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:118:15
+   |
+LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "thiscall" is not supported on this target
+  --> $DIR/unsupported.rs:141:20
+   |
+LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "stdcall" is not supported on this target
+  --> $DIR/unsupported.rs:167:19
+   |
+LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr
index dfb4b573349..b2f24381336 100644
--- a/tests/ui/abi/unsupported.arm.stderr
+++ b/tests/ui/abi/unsupported.arm.stderr
@@ -185,3 +185,102 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 17 previous errors; 9 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "riscv-interrupt-m" is not supported on this target
+  --> $DIR/unsupported.rs:96:17
+   |
+LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "x86-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:118:15
+   |
+LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "thiscall" is not supported on this target
+  --> $DIR/unsupported.rs:141:20
+   |
+LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "stdcall" is not supported on this target
+  --> $DIR/unsupported.rs:167:19
+   |
+LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr
index d7b76a4730b..94bd9b8af90 100644
--- a/tests/ui/abi/unsupported.i686.stderr
+++ b/tests/ui/abi/unsupported.i686.stderr
@@ -143,3 +143,80 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 13 previous errors; 7 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "aapcs" is not supported on this target
+  --> $DIR/unsupported.rs:51:17
+   |
+LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "riscv-interrupt-m" is not supported on this target
+  --> $DIR/unsupported.rs:96:17
+   |
+LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr
index eef2ead4f0f..c6ff47283c6 100644
--- a/tests/ui/abi/unsupported.riscv32.stderr
+++ b/tests/ui/abi/unsupported.riscv32.stderr
@@ -185,3 +185,102 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 17 previous errors; 9 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "aapcs" is not supported on this target
+  --> $DIR/unsupported.rs:51:17
+   |
+LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "x86-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:118:15
+   |
+LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "thiscall" is not supported on this target
+  --> $DIR/unsupported.rs:141:20
+   |
+LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "stdcall" is not supported on this target
+  --> $DIR/unsupported.rs:167:19
+   |
+LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr
index eef2ead4f0f..c6ff47283c6 100644
--- a/tests/ui/abi/unsupported.riscv64.stderr
+++ b/tests/ui/abi/unsupported.riscv64.stderr
@@ -185,3 +185,102 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 17 previous errors; 9 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "aapcs" is not supported on this target
+  --> $DIR/unsupported.rs:51:17
+   |
+LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "x86-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:118:15
+   |
+LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "thiscall" is not supported on this target
+  --> $DIR/unsupported.rs:141:20
+   |
+LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "stdcall" is not supported on this target
+  --> $DIR/unsupported.rs:167:19
+   |
+LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr
index 80613d83e58..0a9f9a69123 100644
--- a/tests/ui/abi/unsupported.x64.stderr
+++ b/tests/ui/abi/unsupported.x64.stderr
@@ -185,3 +185,102 @@ LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {}
 error: aborting due to 17 previous errors; 9 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "ptx-kernel" is not supported on this target
+  --> $DIR/unsupported.rs:35:15
+   |
+LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "aapcs" is not supported on this target
+  --> $DIR/unsupported.rs:51:17
+   |
+LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "msp430-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:73:18
+   |
+LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "avr-interrupt" is not supported on this target
+  --> $DIR/unsupported.rs:83:15
+   |
+LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "riscv-interrupt-m" is not supported on this target
+  --> $DIR/unsupported.rs:96:17
+   |
+LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "thiscall" is not supported on this target
+  --> $DIR/unsupported.rs:141:20
+   |
+LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "stdcall" is not supported on this target
+  --> $DIR/unsupported.rs:167:19
+   |
+LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/unsupported.rs:187:21
+   |
+LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
+Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target
+  --> $DIR/unsupported.rs:195:22
+   |
+LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/associated-inherent-types/issue-109299-1.stderr b/tests/ui/associated-inherent-types/issue-109299-1.stderr
index 07a00b6b9a9..77a78da852f 100644
--- a/tests/ui/associated-inherent-types/issue-109299-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-109299-1.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current s
   --> $DIR/issue-109299-1.rs:10:40
    |
 LL | struct Lexer<T>(T);
-   | --------------- associated item `Cursor` not found for this struct
+   | --------------- associated type `Cursor` not found for this struct
 ...
 LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
    |                                        ^^^^^^ associated item not found in `Lexer<T>`
@@ -14,7 +14,7 @@ error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current s
   --> $DIR/issue-109299-1.rs:10:40
    |
 LL | struct Lexer<T>(T);
-   | --------------- associated item `Cursor` not found for this struct
+   | --------------- associated type `Cursor` not found for this struct
 ...
 LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
    |                                        ^^^^^^ associated item not found in `Lexer<T>`
diff --git a/tests/ui/associated-inherent-types/issue-109789.rs b/tests/ui/associated-inherent-types/issue-109789.rs
index 46dd4590141..e3c490b2dc8 100644
--- a/tests/ui/associated-inherent-types/issue-109789.rs
+++ b/tests/ui/associated-inherent-types/issue-109789.rs
@@ -20,5 +20,6 @@ fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
 //~| ERROR mismatched types
 //~| ERROR higher-ranked subtype error
 //~| ERROR higher-ranked subtype error
+//~| ERROR higher-ranked subtype error
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr
index c6ea6c5541d..db860a64826 100644
--- a/tests/ui/associated-inherent-types/issue-109789.stderr
+++ b/tests/ui/associated-inherent-types/issue-109789.stderr
@@ -31,6 +31,14 @@ LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 4 previous errors
+error: higher-ranked subtype error
+  --> $DIR/issue-109789.rs:18:1
+   |
+LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs
index 3255bf20ebd..cad6d48b1c5 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.rs
+++ b/tests/ui/associated-inherent-types/issue-111404-1.rs
@@ -12,5 +12,6 @@ fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
 //~| ERROR mismatched types [E0308]
 //~| ERROR higher-ranked subtype error
 //~| ERROR higher-ranked subtype error
+//~| ERROR higher-ranked subtype error
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index 5074c877a8e..ce49126c316 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -31,6 +31,14 @@ LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 4 previous errors
+error: higher-ranked subtype error
+  --> $DIR/issue-111404-1.rs:10:1
+   |
+LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr
index 9bd5a842fdc..a247d6d5b45 100644
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `Pr` not found for `S<bool>` in the current scope
   --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23
    |
 LL | struct S<T>(T);
-   | ----------- associated item `Pr` not found for this struct
+   | ----------- associated type `Pr` not found for this struct
 ...
 LL |     let _: S::<bool>::Pr = ();
    |                       ^^ associated item not found in `S<bool>`
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr
index 1871407c64f..6194c6ff4d7 100644
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the c
   --> $DIR/not-found-self-type-differs.rs:15:32
    |
 LL | struct Family<T>(T);
-   | ---------------- associated item `Proj` not found for this struct
+   | ---------------- associated type `Proj` not found for this struct
 ...
 LL |     let _: Family<Option<()>>::Proj;
    |                                ^^^^ associated item not found in `Family<Option<()>>`
@@ -15,7 +15,7 @@ error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the curr
   --> $DIR/not-found-self-type-differs.rs:16:40
    |
 LL | struct Family<T>(T);
-   | ---------------- associated item `Proj` not found for this struct
+   | ---------------- associated type `Proj` not found for this struct
 ...
 LL |     let _: Family<std::path::PathBuf>::Proj = ();
    |                                        ^^^^ associated item not found in `Family<PathBuf>`
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr
index 73657906761..dd51192e06f 100644
--- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr
@@ -2,7 +2,7 @@ error: the associated type `Yield` exists for `Container<[u8]>`, but its trait b
   --> $DIR/not-found-unsatisfied-bounds-0.rs:19:29
    |
 LL | struct Container<T: ?Sized>(T);
-   | --------------------------- associated item `Yield` not found for this struct
+   | --------------------------- associated type `Yield` not found for this struct
 ...
 LL |     let _: Container<[u8]>::Yield = 1;
    |                             ^^^^^ associated type cannot be referenced on `Container<[u8]>` due to unsatisfied trait bounds
@@ -14,7 +14,7 @@ error: the associated type `Combination` exists for `Duple<String, Rc<str>>`, bu
   --> $DIR/not-found-unsatisfied-bounds-0.rs:20:45
    |
 LL | struct Duple<T, U>(T, U);
-   | ------------------ associated item `Combination` not found for this struct
+   | ------------------ associated type `Combination` not found for this struct
 ...
 LL |     let _: Duple<String, std::rc::Rc<str>>::Combination;
    |                                             ^^^^^^^^^^^ associated type cannot be referenced on `Duple<String, Rc<str>>` due to unsatisfied trait bounds
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr
index 0d5f781dc63..c27e1f49faa 100644
--- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr
@@ -5,7 +5,7 @@ LL |     let _: Container<T>::Proj = String::new();
    |                          ^^^^ associated type cannot be referenced on `Container<T>` due to unsatisfied trait bounds
 ...
 LL | struct Container<T>(T);
-   | ------------------- associated item `Proj` not found for this struct
+   | ------------------- associated type `Proj` not found for this struct
    |
    = note: the following trait bounds were not satisfied:
            `T: Clone`
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr
index 1613af6b8b1..db6c71a626f 100644
--- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr
@@ -2,7 +2,7 @@ error: the associated type `X` exists for `S<Featureless, Featureless>`, but its
   --> $DIR/not-found-unsatisfied-bounds-in-multiple-impls.rs:19:43
    |
 LL | struct S<A, B>(A, B);
-   | -------------- associated item `X` not found for this struct
+   | -------------- associated type `X` not found for this struct
 LL | struct Featureless;
    | ------------------ doesn't satisfy `Featureless: One` or `Featureless: Two`
 ...
diff --git a/tests/ui/async-await/issues/issue-63388-2.rs b/tests/ui/async-await/issues/issue-63388-2.rs
index 8bb5cfa4a59..d9dc602bd1c 100644
--- a/tests/ui/async-await/issues/issue-63388-2.rs
+++ b/tests/ui/async-await/issues/issue-63388-2.rs
@@ -12,7 +12,6 @@ impl Xyz {
     ) -> &dyn Foo //~ ERROR missing lifetime specifier
     {
         foo
-        //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
     }
 }
 
diff --git a/tests/ui/async-await/issues/issue-63388-2.stderr b/tests/ui/async-await/issues/issue-63388-2.stderr
index 7e3c0a1227d..45843bc72cd 100644
--- a/tests/ui/async-await/issues/issue-63388-2.stderr
+++ b/tests/ui/async-await/issues/issue-63388-2.stderr
@@ -12,16 +12,6 @@ help: consider using the `'a` lifetime
 LL |     ) -> &'a dyn Foo
    |           ++
 
-error[E0621]: explicit lifetime required in the type of `foo`
-  --> $DIR/issue-63388-2.rs:14:9
-   |
-LL |         foo: &dyn Foo, bar: &'a dyn Foo
-   |              -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
-...
-LL |         foo
-   |         ^^^ lifetime `'a` required
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0106, E0621.
-For more information about an error, try `rustc --explain E0106`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs
index 686dcb277f8..d94572ef5d6 100644
--- a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs
+++ b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs
@@ -10,14 +10,15 @@
 
 #[cfg_attr(
     any(
-        target_os = "linux",
         target_os = "android",
+        target_os = "dragonfly",
         target_os = "freebsd",
+        target_os = "haiku",
+        target_os = "illumos",
+        target_os = "linux",
         target_os = "netbsd",
+        target_os = "nto",
         target_os = "openbsd",
-        target_os = "dragonfly",
-        target_os = "illumos",
-        target_os = "haiku"
     ),
     link_section = ".init_array"
 )]
diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs
index 99f83f22d17..da7bb76fc14 100644
--- a/tests/ui/c-variadic/variadic-ffi-2.rs
+++ b/tests/ui/c-variadic/variadic-ffi-2.rs
@@ -1,8 +1,6 @@
-//@ ignore-arm stdcall isn't supported
 #![feature(extended_varargs_abi_support)]
 
-#[allow(unsupported_fn_ptr_calling_conventions)]
-fn baz(f: extern "stdcall" fn(usize, ...)) {
+fn baz(f: extern "Rust" fn(usize, ...)) {
     //~^ ERROR: C-variadic function must have a compatible calling convention,
     // like C, cdecl, system, aapcs, win64, sysv64 or efiapi
     f(22, 44);
diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr
index e52de93a926..9f8dcefdb03 100644
--- a/tests/ui/c-variadic/variadic-ffi-2.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-2.stderr
@@ -1,8 +1,8 @@
 error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
-  --> $DIR/variadic-ffi-2.rs:5:11
+  --> $DIR/variadic-ffi-2.rs:3:11
    |
-LL | fn baz(f: extern "stdcall" fn(usize, ...)) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
+LL | fn baz(f: extern "Rust" fn(usize, ...)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
index 5704a33cc87..78f6dca1818 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
@@ -2,8 +2,6 @@
 // Check that you can cast between different pointers to trait objects
 // whose vtable have the same kind (both lengths, or both trait pointers).
 
-#![feature(unsized_tuple_coercion)]
-
 trait Bar { //~ WARN trait `Bar` is never used
     fn bar(&self) { println!("Bar!"); }
 }
@@ -19,10 +17,6 @@ fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
     u as *const BarS<T>
 }
 
-fn tuple_i32_to_u32<T:?Sized>(u: *const (i32, T)) -> *const (u32, T) {
-    u as *const (u32, T)
-}
-
 
 fn main() {
     let s = FooS([0,1,2]);
@@ -31,14 +25,4 @@ fn main() {
     let bar_ref : *const BarS<[u32]> = foo_to_bar(u);
     let z : &BarS<[u32]> = unsafe{&*bar_ref};
     assert_eq!(&z.0, &[0,1,2]);
-
-    // this assumes that tuple reprs for (i32, _) and (u32, _) are
-    // the same.
-    let s = (0i32, [0, 1, 2]);
-    let u: &(i32, [u8]) = &s;
-    let u: *const (i32, [u8]) = u;
-    let u_u32 : *const (u32, [u8]) = tuple_i32_to_u32(u);
-    unsafe {
-        assert_eq!(&(*u_u32).1, &[0, 1, 2]);
-    }
 }
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
index 4f57e2e7df7..01277fd632e 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
@@ -1,5 +1,5 @@
 warning: trait `Bar` is never used
-  --> $DIR/cast-rfc0401-vtable-kinds.rs:7:7
+  --> $DIR/cast-rfc0401-vtable-kinds.rs:5:7
    |
 LL | trait Bar {
    |       ^^^
diff --git a/tests/ui/cast/ptr-to-trait-obj-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-add-auto.rs
index 46e72ea0877..3a1e667d03a 100644
--- a/tests/ui/cast/ptr-to-trait-obj-add-auto.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-add-auto.rs
@@ -1,18 +1,20 @@
-//@ check-pass
-
 trait Trait<'a> {}
 
 fn add_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send) {
     x as _
-    //~^ warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
-    //~| warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~^ ERROR cannot add auto trait `Send` to dyn bound via pointer cast
+    //~| NOTE unsupported cast
+    //~| NOTE this could allow UB elsewhere
+    //~| HELP use `transmute` if you're sure this is sound
 }
 
 // (to test diagnostic list formatting)
 fn add_multiple_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send + Sync + Unpin) {
     x as _
-    //~^ warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
-    //~| warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~^ ERROR cannot add auto traits `Send`, `Sync`, and `Unpin` to dyn bound via pointer cast
+    //~| NOTE unsupported cast
+    //~| NOTE this could allow UB elsewhere
+    //~| HELP use `transmute` if you're sure this is sound
 }
 
 fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr
index e5ef8bf76b4..b64ca9b32bf 100644
--- a/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr
@@ -1,43 +1,21 @@
-warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
-  --> $DIR/ptr-to-trait-obj-add-auto.rs:6:5
+error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
+  --> $DIR/ptr-to-trait-obj-add-auto.rs:4:5
    |
 LL |     x as _
-   |     ^^^^^^
+   |     ^^^^^^ unsupported cast
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
-   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
+   = note: this could allow UB elsewhere
+   = help: use `transmute` if you're sure this is sound
 
-warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
+error[E0804]: cannot add auto traits `Send`, `Sync`, and `Unpin` to dyn bound via pointer cast
   --> $DIR/ptr-to-trait-obj-add-auto.rs:13:5
    |
 LL |     x as _
-   |     ^^^^^^
+   |     ^^^^^^ unsupported cast
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
+   = note: this could allow UB elsewhere
+   = help: use `transmute` if you're sure this is sound
 
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
-  --> $DIR/ptr-to-trait-obj-add-auto.rs:6:5
-   |
-LL |     x as _
-   |     ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
-   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
-
-Future breakage diagnostic:
-warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
-  --> $DIR/ptr-to-trait-obj-add-auto.rs:13:5
-   |
-LL |     x as _
-   |     ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
-   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0804`.
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 8675f7a61c7..5b82d3f539f 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -151,6 +151,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `mp`
 `mp1e2`
 `msa`
+`msync`
 `mte`
 `multivalue`
 `mutable-globals`
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
index 63260b5c78f..beb0ab70cc7 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
@@ -11,3 +11,13 @@ LL |         core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(i32
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0658`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target
+  --> $DIR/gate_test.rs:5:39
+   |
+LL |         core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(i32, i32, i32, i32) -> i32>(
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
index 30a45ce377e..b73611c79b2 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
@@ -54,12 +54,6 @@ warning: type `v17` should have an upper camel case name
 LL |     pub struct v17<const v10: usize, const v7: v11> {
    |                ^^^ help: convert the identifier to upper camel case (notice the capitalization): `V17`
 
-error[E0425]: cannot find function `v6` in this scope
-  --> $DIR/unevaluated-const-ice-119731.rs:13:35
-   |
-LL |     const v0: [[usize; v4]; v4] = v6(v8);
-   |                                   ^^ not found in this scope
-
 error: `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
   --> $DIR/unevaluated-const-ice-119731.rs:16:48
    |
@@ -72,6 +66,12 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
 LL + #![feature(adt_const_params)]
    |
 
+error[E0425]: cannot find function `v6` in this scope
+  --> $DIR/unevaluated-const-ice-119731.rs:13:35
+   |
+LL |     const v0: [[usize; v4]; v4] = v6(v8);
+   |                                   ^^ not found in this scope
+
 error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
   --> $DIR/unevaluated-const-ice-119731.rs:28:37
    |
diff --git a/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs b/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs
new file mode 100644
index 00000000000..d7df9c22afd
--- /dev/null
+++ b/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs
@@ -0,0 +1,15 @@
+#![feature(min_generic_const_args)]
+#![expect(incomplete_features)]
+
+trait Tr {
+    const N: usize;
+}
+
+struct Blah<const N: usize>;
+
+fn foo() -> Blah<{ Tr::N }> {
+    //~^ ERROR ambiguous associated constant
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/mgca/ambiguous-assoc-const.stderr b/tests/ui/const-generics/mgca/ambiguous-assoc-const.stderr
new file mode 100644
index 00000000000..11c63bdbcf4
--- /dev/null
+++ b/tests/ui/const-generics/mgca/ambiguous-assoc-const.stderr
@@ -0,0 +1,15 @@
+error[E0223]: ambiguous associated constant
+  --> $DIR/ambiguous-assoc-const.rs:10:20
+   |
+LL | fn foo() -> Blah<{ Tr::N }> {
+   |                    ^^^^^
+   |
+help: if there were a type named `Example` that implemented `Tr`, you could use the fully-qualified path
+   |
+LL - fn foo() -> Blah<{ Tr::N }> {
+LL + fn foo() -> Blah<{ <Example as Tr>::N }> {
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs
new file mode 100644
index 00000000000..a11314c11aa
--- /dev/null
+++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs
@@ -0,0 +1,14 @@
+#![feature(min_generic_const_args)]
+#![allow(incomplete_features)]
+
+pub trait Tr {
+    const SIZE: usize;
+}
+
+fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
+    //~^ ERROR type_const
+    [(); T::SIZE]
+    //~^ ERROR type_const
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr
new file mode 100644
index 00000000000..7872e096762
--- /dev/null
+++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr
@@ -0,0 +1,18 @@
+error: use of trait associated const without `#[type_const]`
+  --> $DIR/assoc-const-without-type_const.rs:8:35
+   |
+LL | fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
+   |                                   ^^^^^^^
+   |
+   = note: the declaration in the trait must be marked with `#[type_const]`
+
+error: use of trait associated const without `#[type_const]`
+  --> $DIR/assoc-const-without-type_const.rs:10:10
+   |
+LL |     [(); T::SIZE]
+   |          ^^^^^^^
+   |
+   = note: the declaration in the trait must be marked with `#[type_const]`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/const-generics/mgca/assoc-const.rs b/tests/ui/const-generics/mgca/assoc-const.rs
new file mode 100644
index 00000000000..fb5b4308a7f
--- /dev/null
+++ b/tests/ui/const-generics/mgca/assoc-const.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+
+#![feature(min_generic_const_args)]
+#![allow(incomplete_features)]
+
+pub trait Tr<X> {
+    #[type_const]
+    const SIZE: usize;
+}
+
+fn mk_array<T: Tr<bool>>(_x: T) -> [(); <T as Tr<bool>>::SIZE] {
+    [(); T::SIZE]
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs
new file mode 100644
index 00000000000..1e9673a56b5
--- /dev/null
+++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs
@@ -0,0 +1,17 @@
+trait Tr {
+    #[type_const()]
+    //~^ ERROR malformed
+    //~| ERROR experimental
+    const N: usize;
+}
+
+struct S;
+
+impl Tr for S {
+    #[type_const]
+    //~^ ERROR must only be applied to trait associated constants
+    //~| ERROR experimental
+    const N: usize = 0;
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr
new file mode 100644
index 00000000000..579aff849d6
--- /dev/null
+++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr
@@ -0,0 +1,35 @@
+error: malformed `type_const` attribute input
+  --> $DIR/bad-type_const-syntax.rs:2:5
+   |
+LL |     #[type_const()]
+   |     ^^^^^^^^^^^^^^^ help: must be of the form: `#[type_const]`
+
+error[E0658]: the `#[type_const]` attribute is an experimental feature
+  --> $DIR/bad-type_const-syntax.rs:2:5
+   |
+LL |     #[type_const()]
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
+   = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the `#[type_const]` attribute is an experimental feature
+  --> $DIR/bad-type_const-syntax.rs:11:5
+   |
+LL |     #[type_const]
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
+   = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: `#[type_const]` must only be applied to trait associated constants
+  --> $DIR/bad-type_const-syntax.rs:11:5
+   |
+LL |     #[type_const]
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/const-generics/mgca/inherent-const-gating.rs b/tests/ui/const-generics/mgca/inherent-const-gating.rs
new file mode 100644
index 00000000000..c39b8e6f7f6
--- /dev/null
+++ b/tests/ui/const-generics/mgca/inherent-const-gating.rs
@@ -0,0 +1,13 @@
+#![feature(min_generic_const_args)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl S {
+    const N: usize = 42;
+}
+
+fn main() {
+    let _x: [(); S::N] = todo!();
+    //~^ ERROR inherent associated types are unstable
+}
diff --git a/tests/ui/const-generics/mgca/inherent-const-gating.stderr b/tests/ui/const-generics/mgca/inherent-const-gating.stderr
new file mode 100644
index 00000000000..71bb11ae700
--- /dev/null
+++ b/tests/ui/const-generics/mgca/inherent-const-gating.stderr
@@ -0,0 +1,13 @@
+error[E0658]: inherent associated types are unstable
+  --> $DIR/inherent-const-gating.rs:11:18
+   |
+LL |     let _x: [(); S::N] = todo!();
+   |                  ^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/const-slice-array-deref.stderr b/tests/ui/consts/const-slice-array-deref.stderr
index 346685380cc..b1d06928088 100644
--- a/tests/ui/consts/const-slice-array-deref.stderr
+++ b/tests/ui/consts/const-slice-array-deref.stderr
@@ -5,6 +5,7 @@ LL | const ONE: [u16] = [1];
    |            ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u16]`
+   = note: statics and constants must have a statically known size
 
 error[E0308]: mismatched types
   --> $DIR/const-slice-array-deref.rs:1:20
diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr
index 7931d7adafd..8328e19aac2 100644
--- a/tests/ui/consts/const-unsized.stderr
+++ b/tests/ui/consts/const-unsized.stderr
@@ -5,6 +5,7 @@ LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
    |                ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
+   = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/const-unsized.rs:7:18
@@ -13,6 +14,7 @@ LL | const CONST_FOO: str = *"foo";
    |                  ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
+   = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time
   --> $DIR/const-unsized.rs:11:18
@@ -21,6 +23,7 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
    |                  ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
+   = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/const-unsized.rs:15:20
@@ -29,6 +32,7 @@ LL | static STATIC_BAR: str = *"bar";
    |                    ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
+   = note: statics and constants must have a statically known size
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/const-unsized.rs:3:35
diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr
index 8665d9b6852..3980a7e9b93 100644
--- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr
+++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr
@@ -30,6 +30,7 @@ LL |     static FOO: Sync = AtomicUsize::new(0);
    |                 ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
+   = note: statics and constants must have a statically known size
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.rs b/tests/ui/consts/dont-ctfe-unsized-initializer.rs
new file mode 100644
index 00000000000..cca38b760dc
--- /dev/null
+++ b/tests/ui/consts/dont-ctfe-unsized-initializer.rs
@@ -0,0 +1,7 @@
+static S: str = todo!();
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+
+const C: str = todo!();
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+
+fn main() {}
diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.stderr b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr
new file mode 100644
index 00000000000..e69790fc182
--- /dev/null
+++ b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/dont-ctfe-unsized-initializer.rs:1:11
+   |
+LL | static S: str = todo!();
+   |           ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: statics and constants must have a statically known size
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/dont-ctfe-unsized-initializer.rs:4:10
+   |
+LL | const C: str = todo!();
+   |          ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: statics and constants must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/consts/issue-39974.stderr b/tests/ui/consts/issue-39974.stderr
index a371ea5709e..d03f709b0ea 100644
--- a/tests/ui/consts/issue-39974.stderr
+++ b/tests/ui/consts/issue-39974.stderr
@@ -1,4 +1,10 @@
 error[E0308]: mismatched types
+  --> $DIR/issue-39974.rs:5:19
+   |
+LL |     f: [[f64; 2]; LENGTH],
+   |                   ^^^^^^ expected `usize`, found `f64`
+
+error[E0308]: mismatched types
   --> $DIR/issue-39974.rs:1:21
    |
 LL | const LENGTH: f64 = 2;
@@ -9,12 +15,6 @@ help: use a float literal
 LL | const LENGTH: f64 = 2.0;
    |                      ++
 
-error[E0308]: mismatched types
-  --> $DIR/issue-39974.rs:5:19
-   |
-LL |     f: [[f64; 2]; LENGTH],
-   |                   ^^^^^^ expected `usize`, found `f64`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/crate-loading/crateresolve1.stderr b/tests/ui/crate-loading/crateresolve1.stderr
index 47131a96bf4..b17330fb9d9 100644
--- a/tests/ui/crate-loading/crateresolve1.stderr
+++ b/tests/ui/crate-loading/crateresolve1.stderr
@@ -4,9 +4,9 @@ error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
 LL | extern crate crateresolve1;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib
-   = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib
-   = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib
+   = note: candidate #1: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-1.somelib
+   = note: candidate #2: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-2.somelib
+   = note: candidate #3: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-3.somelib
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/crate-loading/crateresolve2.stderr b/tests/ui/crate-loading/crateresolve2.stderr
index 3dc89dabde6..0c488f3fd07 100644
--- a/tests/ui/crate-loading/crateresolve2.stderr
+++ b/tests/ui/crate-loading/crateresolve2.stderr
@@ -4,9 +4,9 @@ error[E0464]: multiple candidates for `rmeta` dependency `crateresolve2` found
 LL | extern crate crateresolve2;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta
-   = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta
-   = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta
+   = note: candidate #1: $TEST_BUILD_DIR/auxiliary/libcrateresolve2-1.rmeta
+   = note: candidate #2: $TEST_BUILD_DIR/auxiliary/libcrateresolve2-2.rmeta
+   = note: candidate #3: $TEST_BUILD_DIR/auxiliary/libcrateresolve2-3.rmeta
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/diagnostic-width/E0271.ascii.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr
index 9a9c12a938f..ad5f53e44be 100644
--- a/tests/ui/diagnostic-width/E0271.ascii.stderr
+++ b/tests/ui/diagnostic-width/E0271.ascii.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
-  --> $DIR/E0271.rs:20:5
+  --> $DIR/E0271.rs:19:5
    |
 LL | /     Box::new(
 LL | |         Ok::<_, ()>(
@@ -10,12 +10,12 @@ LL | |     )
    | |_____^ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
    |
 note: expected this to be `Foo`
-  --> $DIR/E0271.rs:10:18
+  --> $DIR/E0271.rs:9:18
    |
 LL |     type Error = E;
    |                  ^
    = note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0271.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs
index 06187721041..522bfb5b93f 100644
--- a/tests/ui/diagnostic-width/E0271.rs
+++ b/tests/ui/diagnostic-width/E0271.rs
@@ -1,7 +1,6 @@
 //@ revisions: ascii unicode
 //@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
 //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 trait Future {
     type Error;
 }
diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr
index 9c3deae6660..91adf834101 100644
--- a/tests/ui/diagnostic-width/E0271.unicode.stderr
+++ b/tests/ui/diagnostic-width/E0271.unicode.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
-   ╭▸ $DIR/E0271.rs:20:5
+   ╭▸ $DIR/E0271.rs:19:5

 LL │ ┏     Box::new(
 LL │ ┃         Ok::<_, ()>(
@@ -10,12 +10,12 @@ LL │ ┃     )
    │ ┗━━━━━┛ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
    ╰╴
 note: expected this to be `Foo`
-   ╭▸ $DIR/E0271.rs:10:18
+   ╭▸ $DIR/E0271.rs:9:18

 LL │     type Error = E;
    │                  ━
    ├ note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
-   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/E0271.long-type-$LONG_TYPE_HASH.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/binop.rs b/tests/ui/diagnostic-width/binop.rs
index 60ba40b8047..9e4e837f386 100644
--- a/tests/ui/diagnostic-width/binop.rs
+++ b/tests/ui/diagnostic-width/binop.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/binop.stderr b/tests/ui/diagnostic-width/binop.stderr
index fd69129c33e..92723df5a9b 100644
--- a/tests/ui/diagnostic-width/binop.stderr
+++ b/tests/ui/diagnostic-width/binop.stderr
@@ -1,21 +1,21 @@
 error[E0369]: cannot add `(..., ..., ..., ...)` to `(..., ..., ..., ...)`
-  --> $DIR/binop.rs:10:7
+  --> $DIR/binop.rs:8:7
    |
 LL |     x + x;
    |     - ^ - (..., ..., ..., ...)
    |     |
    |     (..., ..., ..., ...)
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/binop.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0600]: cannot apply unary operator `!` to type `(..., ..., ..., ...)`
-  --> $DIR/binop.rs:14:5
+  --> $DIR/binop.rs:12:5
    |
 LL |     !x;
    |     ^^ cannot apply unary operator `!`
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/binop.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/diagnostic-width/long-E0308.ascii.stderr b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
index 83da5586188..d1fdd6c4433 100644
--- a/tests/ui/diagnostic-width/long-E0308.ascii.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:48:9
+  --> $DIR/long-E0308.rs:45:9
    |
 LL |        let x: Atype<
    |  _____________-
@@ -20,11 +20,11 @@ LL |  |     ))))))))))))))))))))))))))))));
    |
    = note: expected struct `Atype<Btype<..., i32>, i32>`
                 found enum `Result<Result<..., _>, _>`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:61:26
+  --> $DIR/long-E0308.rs:58:26
    |
 LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  __________________________^
@@ -36,11 +36,11 @@ LL | |     ))))))))))))))))))))))));
    |
    = note: expected enum `Option<Result<Option<...>, _>>`
               found enum `Result<Result<..., _>, _>`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:92:9
+  --> $DIR/long-E0308.rs:89:9
    |
 LL |       let x: Atype<
    |  ____________-
@@ -56,11 +56,11 @@ LL | |     > = ();
    |
    = note: expected struct `Atype<Btype<..., i32>, i32>`
            found unit type `()`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:95:17
+  --> $DIR/long-E0308.rs:92:17
    |
 LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  ____________--___^
@@ -74,7 +74,7 @@ LL | |     ))))))))))))))))))))))));
    |
    = note: expected unit type `()`
                    found enum `Result<Result<..., _>, _>`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs
index 26383d9418d..94e525e387e 100644
--- a/tests/ui/diagnostic-width/long-E0308.rs
+++ b/tests/ui/diagnostic-width/long-E0308.rs
@@ -2,9 +2,6 @@
 //@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
 //@[unicode] compile-flags: -Zunstable-options --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
 
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
-
 mod a {
     // Force the "short path for unique types" machinery to trip up
     pub struct Atype;
diff --git a/tests/ui/diagnostic-width/long-E0308.unicode.stderr b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
index 54abf576dbd..69e5ca10067 100644
--- a/tests/ui/diagnostic-width/long-E0308.unicode.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:48:9
+   ╭▸ $DIR/long-E0308.rs:45:9

 LL │        let x: Atype<
    │ ┌─────────────┘
@@ -20,11 +20,11 @@ LL │  ┃     ))))))))))))))))))))))))))))));

    ├ note: expected struct `Atype<Btype<..., i32>, i32>`
    │            found enum `Result<Result<..., _>, _>`
-   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:61:26
+   ╭▸ $DIR/long-E0308.rs:58:26

 LL │       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
    │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┛
@@ -36,11 +36,11 @@ LL │ ┃     ))))))))))))))))))))))));

    ├ note: expected enum `Option<Result<Option<...>, _>>`
    │          found enum `Result<Result<..., _>, _>`
-   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:92:9
+   ╭▸ $DIR/long-E0308.rs:89:9

 LL │       let x: Atype<
    │ ┌────────────┘
@@ -56,11 +56,11 @@ LL │ │     > = ();

    ├ note: expected struct `Atype<Btype<..., i32>, i32>`
    │       found unit type `()`
-   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:95:17
+   ╭▸ $DIR/long-E0308.rs:92:17

 LL │       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
    │ ┏━━━━━━━━━━━━┬─━━━┛
@@ -74,7 +74,7 @@ LL │ ┃     ))))))))))))))))))))))));

    ├ note: expected unit type `()`
    │               found enum `Result<Result<..., _>, _>`
-   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0308.long-type-$LONG_TYPE_HASH.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/diagnostic-width/long-E0529.rs b/tests/ui/diagnostic-width/long-E0529.rs
index 3ebc4f5f8c8..759a902da7e 100644
--- a/tests/ui/diagnostic-width/long-E0529.rs
+++ b/tests/ui/diagnostic-width/long-E0529.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/long-E0529.stderr b/tests/ui/diagnostic-width/long-E0529.stderr
index da03e5fab2c..bf3144cc9b6 100644
--- a/tests/ui/diagnostic-width/long-E0529.stderr
+++ b/tests/ui/diagnostic-width/long-E0529.stderr
@@ -1,10 +1,10 @@
 error[E0529]: expected an array or slice, found `(..., ..., ..., ...)`
-  --> $DIR/long-E0529.rs:10:9
+  --> $DIR/long-E0529.rs:9:9
    |
 LL |     let [] = x;
    |         ^^ pattern cannot match with input type `(..., ..., ..., ...)`
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0529.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/long-E0609.rs b/tests/ui/diagnostic-width/long-E0609.rs
index 39442bdeae0..a26d16ad12e 100644
--- a/tests/ui/diagnostic-width/long-E0609.rs
+++ b/tests/ui/diagnostic-width/long-E0609.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/long-E0609.stderr b/tests/ui/diagnostic-width/long-E0609.stderr
index 6815caa6b6b..36ef8545746 100644
--- a/tests/ui/diagnostic-width/long-E0609.stderr
+++ b/tests/ui/diagnostic-width/long-E0609.stderr
@@ -1,10 +1,10 @@
 error[E0609]: no field `field` on type `(..., ..., ..., ...)`
-  --> $DIR/long-E0609.rs:10:7
+  --> $DIR/long-E0609.rs:9:7
    |
 LL |     x.field;
    |       ^^^^^ unknown field
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0609.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/long-E0614.rs b/tests/ui/diagnostic-width/long-E0614.rs
index 0b78444a00d..5e8b3324dd1 100644
--- a/tests/ui/diagnostic-width/long-E0614.rs
+++ b/tests/ui/diagnostic-width/long-E0614.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/long-E0614.stderr b/tests/ui/diagnostic-width/long-E0614.stderr
index 1c16ff617fa..18da20da945 100644
--- a/tests/ui/diagnostic-width/long-E0614.stderr
+++ b/tests/ui/diagnostic-width/long-E0614.stderr
@@ -1,10 +1,10 @@
 error[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced
-  --> $DIR/long-E0614.rs:10:5
+  --> $DIR/long-E0614.rs:9:5
    |
 LL |     *x;
    |     ^^ can't be dereferenced
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0614.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/long-E0618.rs b/tests/ui/diagnostic-width/long-E0618.rs
index f8626ab9455..b499bedc394 100644
--- a/tests/ui/diagnostic-width/long-E0618.rs
+++ b/tests/ui/diagnostic-width/long-E0618.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/long-E0618.stderr b/tests/ui/diagnostic-width/long-E0618.stderr
index f0838cbddcc..05bf999c142 100644
--- a/tests/ui/diagnostic-width/long-E0618.stderr
+++ b/tests/ui/diagnostic-width/long-E0618.stderr
@@ -1,5 +1,5 @@
 error[E0618]: expected function, found `(..., ..., ..., ...)`
-  --> $DIR/long-E0618.rs:10:5
+  --> $DIR/long-E0618.rs:9:5
    |
 LL | fn foo(x: D) {
    |        - `x` has type `(..., ..., ..., ...)`
@@ -8,7 +8,7 @@ LL |     x();
    |     |
    |     call expression requires function
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0618.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/long-e0277.rs b/tests/ui/diagnostic-width/long-e0277.rs
index 9b3bd8bb728..369fd8daea7 100644
--- a/tests/ui/diagnostic-width/long-e0277.rs
+++ b/tests/ui/diagnostic-width/long-e0277.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/long-e0277.stderr b/tests/ui/diagnostic-width/long-e0277.stderr
index a57270df7e2..ff897151165 100644
--- a/tests/ui/diagnostic-width/long-e0277.stderr
+++ b/tests/ui/diagnostic-width/long-e0277.stderr
@@ -1,21 +1,21 @@
 error[E0277]: the trait bound `(..., ..., ..., ...): Trait` is not satisfied
-  --> $DIR/long-e0277.rs:14:21
+  --> $DIR/long-e0277.rs:12:21
    |
 LL |     require_trait::<D>();
    |                     ^ unsatisfied trait bound
    |
    = help: the trait `Trait` is not implemented for `(..., ..., ..., ...)`
 help: this trait has no implementations, consider adding one
-  --> $DIR/long-e0277.rs:9:1
+  --> $DIR/long-e0277.rs:7:1
    |
 LL | trait Trait {}
    | ^^^^^^^^^^^
 note: required by a bound in `require_trait`
-  --> $DIR/long-e0277.rs:11:21
+  --> $DIR/long-e0277.rs:9:21
    |
 LL | fn require_trait<T: Trait>() {}
    |                     ^^^^^ required by this bound in `require_trait`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-e0277.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.rs b/tests/ui/diagnostic-width/non-copy-type-moved.rs
index a220c62775e..845457f7e30 100644
--- a/tests/ui/diagnostic-width/non-copy-type-moved.rs
+++ b/tests/ui/diagnostic-width/non-copy-type-moved.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 
 type A = (String, String, String, String);
 type B = (A, A, A, A);
diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.stderr b/tests/ui/diagnostic-width/non-copy-type-moved.stderr
index 254542c7b39..16c01c858b7 100644
--- a/tests/ui/diagnostic-width/non-copy-type-moved.stderr
+++ b/tests/ui/diagnostic-width/non-copy-type-moved.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/non-copy-type-moved.rs:16:14
+  --> $DIR/non-copy-type-moved.rs:14:14
    |
 LL | fn foo(x: D) {
    |        - move occurs because `x` has type `(..., ..., ..., ...)`, which does not implement the `Copy` trait
@@ -8,7 +8,7 @@ LL |     let _a = x;
 LL |     let _b = x;
    |              ^ value used here after move
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/non-copy-type-moved.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 help: consider cloning the value if the performance cost is acceptable
    |
diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
index c8845af3183..13fe967ba5f 100644
--- a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
+++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: --diagnostic-width=100 -Zwrite-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
index a95e1709148..a99657ca113 100644
--- a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
+++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/secondary-label-with-long-type.rs:11:9
+  --> $DIR/secondary-label-with-long-type.rs:9:9
    |
 LL |     let () = x;
    |         ^^   - this expression has type `((..., ..., ..., ...), ..., ..., ...)`
@@ -8,7 +8,7 @@ LL |     let () = x;
    |
    = note:  expected tuple `((..., ..., ..., ...), ..., ..., ...)`
            found unit type `()`
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/secondary-label-with-long-type.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/dst/dst-bad-assign-3.rs b/tests/ui/dst/dst-bad-assign-3.rs
index d199864d99c..f96ecf7762c 100644
--- a/tests/ui/dst/dst-bad-assign-3.rs
+++ b/tests/ui/dst/dst-bad-assign-3.rs
@@ -1,8 +1,6 @@
 // Forbid assignment into a dynamically sized type.
 
-#![feature(unsized_tuple_coercion)]
-
-type Fat<T> = (isize, &'static str, T);
+struct Fat<T: ?Sized>(isize, &'static str, T);
 
 #[derive(PartialEq,Eq)]
 struct Bar;
@@ -28,7 +26,7 @@ impl ToBar for Bar1 {
 
 pub fn main() {
     // Assignment.
-    let f5: &mut Fat<dyn ToBar> = &mut (5, "some str", Bar1 {f :42});
+    let f5: &mut Fat<dyn ToBar> = &mut Fat(5, "some str", Bar1 {f :42});
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.2 = Bar1 {f: 36};
     //~^ ERROR mismatched types
diff --git a/tests/ui/dst/dst-bad-assign-3.stderr b/tests/ui/dst/dst-bad-assign-3.stderr
index 007f6b898be..4aa1677e751 100644
--- a/tests/ui/dst/dst-bad-assign-3.stderr
+++ b/tests/ui/dst/dst-bad-assign-3.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/dst-bad-assign-3.rs:33:12
+  --> $DIR/dst-bad-assign-3.rs:31:12
    |
 LL |     f5.2 = Bar1 {f: 36};
    |     ----   ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
@@ -11,7 +11,7 @@ LL |     f5.2 = Bar1 {f: 36};
    = help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
 
 error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
-  --> $DIR/dst-bad-assign-3.rs:33:5
+  --> $DIR/dst-bad-assign-3.rs:31:5
    |
 LL |     f5.2 = Bar1 {f: 36};
    |     ^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/dst/dst-bad-coerce1.rs b/tests/ui/dst/dst-bad-coerce1.rs
index 7ef237e39e3..5ee0bfa9fbf 100644
--- a/tests/ui/dst/dst-bad-coerce1.rs
+++ b/tests/ui/dst/dst-bad-coerce1.rs
@@ -1,7 +1,5 @@
 // Attempt to change the type as well as unsizing.
 
-#![feature(unsized_tuple_coercion)]
-
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -21,16 +19,4 @@ pub fn main() {
     let f2: &Fat<Foo> = &f1;
     let f3: &Fat<dyn Bar> = f2;
     //~^ ERROR `Foo: Bar` is not satisfied
-
-    // Tuple with a vec of isize.
-    let f1 = ([1, 2, 3],);
-    let f2: &([isize; 3],) = &f1;
-    let f3: &([usize],) = f2;
-    //~^ ERROR mismatched types
-
-    // Tuple with a trait.
-    let f1 = (Foo,);
-    let f2: &(Foo,) = &f1;
-    let f3: &(dyn Bar,) = f2;
-    //~^ ERROR `Foo: Bar` is not satisfied
 }
diff --git a/tests/ui/dst/dst-bad-coerce1.stderr b/tests/ui/dst/dst-bad-coerce1.stderr
index 455d15e935f..68456b8642c 100644
--- a/tests/ui/dst/dst-bad-coerce1.stderr
+++ b/tests/ui/dst/dst-bad-coerce1.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/dst-bad-coerce1.rs:16:29
+  --> $DIR/dst-bad-coerce1.rs:14:29
    |
 LL |     let f3: &Fat<[usize]> = f2;
    |             -------------   ^^ expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
@@ -10,43 +10,19 @@ LL |     let f3: &Fat<[usize]> = f2;
               found reference `&Fat<[isize; 3]>`
 
 error[E0277]: the trait bound `Foo: Bar` is not satisfied
-  --> $DIR/dst-bad-coerce1.rs:22:29
+  --> $DIR/dst-bad-coerce1.rs:20:29
    |
 LL |     let f3: &Fat<dyn Bar> = f2;
    |                             ^^ the trait `Bar` is not implemented for `Foo`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dst-bad-coerce1.rs:10:1
+  --> $DIR/dst-bad-coerce1.rs:8:1
    |
 LL | trait Bar { fn bar(&self) {} }
    | ^^^^^^^^^
    = note: required for the cast from `&Fat<Foo>` to `&Fat<dyn Bar>`
 
-error[E0308]: mismatched types
-  --> $DIR/dst-bad-coerce1.rs:28:27
-   |
-LL |     let f3: &([usize],) = f2;
-   |             -----------   ^^ expected `&([usize],)`, found `&([isize; 3],)`
-   |             |
-   |             expected due to this
-   |
-   = note: expected reference `&([usize],)`
-              found reference `&([isize; 3],)`
-
-error[E0277]: the trait bound `Foo: Bar` is not satisfied
-  --> $DIR/dst-bad-coerce1.rs:34:27
-   |
-LL |     let f3: &(dyn Bar,) = f2;
-   |                           ^^ the trait `Bar` is not implemented for `Foo`
-   |
-help: this trait has no implementations, consider adding one
-  --> $DIR/dst-bad-coerce1.rs:10:1
-   |
-LL | trait Bar { fn bar(&self) {} }
-   | ^^^^^^^^^
-   = note: required for the cast from `&(Foo,)` to `&(dyn Bar,)`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/dst/dst-bad-coerce3.rs b/tests/ui/dst/dst-bad-coerce3.rs
index fd5ee3b57bb..508f009c33e 100644
--- a/tests/ui/dst/dst-bad-coerce3.rs
+++ b/tests/ui/dst/dst-bad-coerce3.rs
@@ -1,7 +1,5 @@
 // Attempt to extend the lifetime as well as unsizing.
 
-#![feature(unsized_tuple_coercion)]
-
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -20,16 +18,6 @@ fn baz<'a>() {
     let f1 = Fat { ptr: Foo };
     let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
     let f3: &'a Fat<dyn Bar> = f2;
-
-    // Tuple with a vec of ints.
-    let f1 = ([1, 2, 3],);
-    let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough
-    let f3: &'a ([isize],) = f2;
-
-    // Tuple with a trait.
-    let f1 = (Foo,);
-    let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough
-    let f3: &'a (dyn Bar,) = f2;
 }
 
 pub fn main() {
diff --git a/tests/ui/dst/dst-bad-coerce3.stderr b/tests/ui/dst/dst-bad-coerce3.stderr
index 1254250bcbd..177535b8c7c 100644
--- a/tests/ui/dst/dst-bad-coerce3.stderr
+++ b/tests/ui/dst/dst-bad-coerce3.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `f1` does not live long enough
-  --> $DIR/dst-bad-coerce3.rs:16:32
+  --> $DIR/dst-bad-coerce3.rs:14:32
    |
 LL | fn baz<'a>() {
    |        -- lifetime `'a` defined here
@@ -15,7 +15,7 @@ LL | }
    | - `f1` dropped here while still borrowed
 
 error[E0597]: `f1` does not live long enough
-  --> $DIR/dst-bad-coerce3.rs:21:25
+  --> $DIR/dst-bad-coerce3.rs:19:25
    |
 LL | fn baz<'a>() {
    |        -- lifetime `'a` defined here
@@ -26,41 +26,9 @@ LL |     let f2: &Fat<Foo> = &f1;
    |                         ^^^ borrowed value does not live long enough
 LL |     let f3: &'a Fat<dyn Bar> = f2;
    |             ---------------- type annotation requires that `f1` is borrowed for `'a`
-...
-LL | }
-   | - `f1` dropped here while still borrowed
-
-error[E0597]: `f1` does not live long enough
-  --> $DIR/dst-bad-coerce3.rs:26:30
-   |
-LL | fn baz<'a>() {
-   |        -- lifetime `'a` defined here
-...
-LL |     let f1 = ([1, 2, 3],);
-   |         -- binding `f1` declared here
-LL |     let f2: &([isize; 3],) = &f1;
-   |                              ^^^ borrowed value does not live long enough
-LL |     let f3: &'a ([isize],) = f2;
-   |             -------------- type annotation requires that `f1` is borrowed for `'a`
-...
-LL | }
-   | - `f1` dropped here while still borrowed
-
-error[E0597]: `f1` does not live long enough
-  --> $DIR/dst-bad-coerce3.rs:31:23
-   |
-LL | fn baz<'a>() {
-   |        -- lifetime `'a` defined here
-...
-LL |     let f1 = (Foo,);
-   |         -- binding `f1` declared here
-LL |     let f2: &(Foo,) = &f1;
-   |                       ^^^ borrowed value does not live long enough
-LL |     let f3: &'a (dyn Bar,) = f2;
-   |             -------------- type annotation requires that `f1` is borrowed for `'a`
 LL | }
    | - `f1` dropped here while still borrowed
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/dst/dst-bad-coerce4.rs b/tests/ui/dst/dst-bad-coerce4.rs
index 9f297915e58..25410aa4fac 100644
--- a/tests/ui/dst/dst-bad-coerce4.rs
+++ b/tests/ui/dst/dst-bad-coerce4.rs
@@ -1,7 +1,5 @@
 // Attempt to coerce from unsized to sized.
 
-#![feature(unsized_tuple_coercion)]
-
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -14,12 +12,4 @@ pub fn main() {
     //~| expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
     //~| expected reference `&Fat<[isize; 3]>`
     //~| found reference `&Fat<[isize]>`
-
-    // Tuple with a vec of isizes.
-    let f1: &([isize],) = &([1, 2, 3],);
-    let f2: &([isize; 3],) = f1;
-    //~^ ERROR mismatched types
-    //~| expected `&([isize; 3],)`, found `&([isize],)`
-    //~| expected reference `&([isize; 3],)`
-    //~| found reference `&([isize],)`
 }
diff --git a/tests/ui/dst/dst-bad-coerce4.stderr b/tests/ui/dst/dst-bad-coerce4.stderr
index 46e7dba817c..5c14c0bfedd 100644
--- a/tests/ui/dst/dst-bad-coerce4.stderr
+++ b/tests/ui/dst/dst-bad-coerce4.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/dst-bad-coerce4.rs:12:32
+  --> $DIR/dst-bad-coerce4.rs:10:32
    |
 LL |     let f2: &Fat<[isize; 3]> = f1;
    |             ----------------   ^^ expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
@@ -9,17 +9,6 @@ LL |     let f2: &Fat<[isize; 3]> = f1;
    = note: expected reference `&Fat<[isize; 3]>`
               found reference `&Fat<[isize]>`
 
-error[E0308]: mismatched types
-  --> $DIR/dst-bad-coerce4.rs:20:30
-   |
-LL |     let f2: &([isize; 3],) = f1;
-   |             --------------   ^^ expected `&([isize; 3],)`, found `&([isize],)`
-   |             |
-   |             expected due to this
-   |
-   = note: expected reference `&([isize; 3],)`
-              found reference `&([isize],)`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/dst/dst-bad-deep-2.rs b/tests/ui/dst/dst-bad-deep-2.rs
index e587399135d..76d35751369 100644
--- a/tests/ui/dst/dst-bad-deep-2.rs
+++ b/tests/ui/dst/dst-bad-deep-2.rs
@@ -3,11 +3,11 @@
 // because it would require stack allocation of an unsized temporary (*g in the
 // test).
 
-#![feature(unsized_tuple_coercion)]
+struct Fat<T: ?Sized>(T);
 
 pub fn main() {
-    let f: ([isize; 3],) = ([5, 6, 7],);
-    let g: &([isize],) = &f;
-    let h: &(([isize],),) = &(*g,);
+    let f: Fat<[isize; 3]> = Fat([5, 6, 7]);
+    let g: &Fat<[isize]> = &f;
+    let h: &Fat<Fat<[isize]>> = &Fat(*g);
     //~^ ERROR the size for values of type
 }
diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr
index c7e9854340f..de3f71d206f 100644
--- a/tests/ui/dst/dst-bad-deep-2.stderr
+++ b/tests/ui/dst/dst-bad-deep-2.stderr
@@ -1,13 +1,17 @@
 error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
-  --> $DIR/dst-bad-deep-2.rs:11:30
+  --> $DIR/dst-bad-deep-2.rs:11:38
    |
-LL |     let h: &(([isize],),) = &(*g,);
-   |                              ^^^^^ doesn't have a size known at compile-time
+LL |     let h: &Fat<Fat<[isize]>> = &Fat(*g);
+   |                                      ^^ doesn't have a size known at compile-time
    |
-   = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`
-   = note: required because it appears within the type `([isize],)`
-   = note: required because it appears within the type `(([isize],),)`
-   = note: tuples must have a statically known size to be initialized
+   = help: within `Fat<[isize]>`, the trait `Sized` is not implemented for `[isize]`
+note: required because it appears within the type `Fat<[isize]>`
+  --> $DIR/dst-bad-deep-2.rs:6:8
+   |
+LL | struct Fat<T: ?Sized>(T);
+   |        ^^^
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs b/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs
index 5e352e930d8..f4576229864 100644
--- a/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs
+++ b/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-#![feature(unsized_tuple_coercion)]
 
 struct Test<T: ?Sized>(T);
 
@@ -14,14 +13,4 @@ fn main() {
     let slice = &[1,2,3];
     let x = Test(&slice);
     let Test(&_slice) = x;
-
-
-    let x = (10, [1,2,3]);
-    let x : &(i32, [i32]) = &x;
-
-    let & ref _y = x;
-
-    let slice = &[1,2,3];
-    let x = (10, &slice);
-    let (_, &_slice) = x;
 }
diff --git a/tests/ui/dynamically-sized-types/dst-raw.rs b/tests/ui/dynamically-sized-types/dst-raw.rs
index c32ee67dab9..111848c5a7f 100644
--- a/tests/ui/dynamically-sized-types/dst-raw.rs
+++ b/tests/ui/dynamically-sized-types/dst-raw.rs
@@ -1,9 +1,6 @@
 //@ run-pass
 // Test DST raw pointers
 
-
-#![feature(unsized_tuple_coercion)]
-
 trait Trait {
     fn foo(&self) -> isize;
 }
@@ -38,14 +35,6 @@ pub fn main() {
     };
     assert_eq!(r, 42);
 
-    // raw DST tuple
-    let p = (A { f: 42 },);
-    let o: *const (dyn Trait,) = &p;
-    let r = unsafe {
-        (&*o).0.foo()
-    };
-    assert_eq!(r, 42);
-
     // raw slice
     let a: *const [_] = &[1, 2, 3];
     unsafe {
@@ -73,15 +62,6 @@ pub fn main() {
         assert_eq!(len, 3);
     }
 
-    // raw DST tuple with slice
-    let c: *const ([_],) = &([1, 2, 3],);
-    unsafe {
-        let b = (&*c).0[0];
-        assert_eq!(b, 1);
-        let len = (&*c).0.len();
-        assert_eq!(len, 3);
-    }
-
     // all of the above with *mut
     let mut x = A { f: 42 };
     let z: *mut dyn Trait = &mut x;
@@ -97,13 +77,6 @@ pub fn main() {
     };
     assert_eq!(r, 42);
 
-    let mut p = (A { f: 42 },);
-    let o: *mut (dyn Trait,) = &mut p;
-    let r = unsafe {
-        (&*o).0.foo()
-    };
-    assert_eq!(r, 42);
-
     let a: *mut [_] = &mut [1, 2, 3];
     unsafe {
         let b = (*a)[2];
@@ -127,12 +100,4 @@ pub fn main() {
         let len = (&*c).f.len();
         assert_eq!(len, 3);
     }
-
-    let c: *mut ([_],) = &mut ([1, 2, 3],);
-    unsafe {
-        let b = (&*c).0[0];
-        assert_eq!(b, 1);
-        let len = (&*c).0.len();
-        assert_eq!(len, 3);
-    }
 }
diff --git a/tests/ui/dynamically-sized-types/dst-trait-tuple.rs b/tests/ui/dynamically-sized-types/dst-trait-tuple.rs
deleted file mode 100644
index 6ab8829859b..00000000000
--- a/tests/ui/dynamically-sized-types/dst-trait-tuple.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//@ run-pass
-#![allow(type_alias_bounds)]
-
-#![allow(unused_features)]
-#![feature(unsized_tuple_coercion)]
-
-type Fat<T: ?Sized> = (isize, &'static str, T);
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-struct Bar;
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-struct Bar1 {
-    f: isize
-}
-
-trait ToBar {
-    fn to_bar(&self) -> Bar;
-    fn to_val(&self) -> isize;
-}
-
-impl ToBar for Bar {
-    fn to_bar(&self) -> Bar {
-        *self
-    }
-    fn to_val(&self) -> isize {
-        0
-    }
-}
-impl ToBar for Bar1 {
-    fn to_bar(&self) -> Bar {
-        Bar
-    }
-    fn to_val(&self) -> isize {
-        self.f
-    }
-}
-
-// x is a fat pointer
-fn foo(x: &Fat<dyn ToBar>) {
-    assert_eq!(x.0, 5);
-    assert_eq!(x.1, "some str");
-    assert_eq!(x.2.to_bar(), Bar);
-    assert_eq!(x.2.to_val(), 42);
-
-    let y = &x.2;
-    assert_eq!(y.to_bar(), Bar);
-    assert_eq!(y.to_val(), 42);
-}
-
-fn bar(x: &dyn ToBar) {
-    assert_eq!(x.to_bar(), Bar);
-    assert_eq!(x.to_val(), 42);
-}
-
-fn baz(x: &Fat<Fat<dyn ToBar>>) {
-    assert_eq!(x.0, 5);
-    assert_eq!(x.1, "some str");
-    assert_eq!((x.2).0, 8);
-    assert_eq!((x.2).1, "deep str");
-    assert_eq!((x.2).2.to_bar(), Bar);
-    assert_eq!((x.2).2.to_val(), 42);
-
-    let y = &(x.2).2;
-    assert_eq!(y.to_bar(), Bar);
-    assert_eq!(y.to_val(), 42);
-
-}
-
-pub fn main() {
-    let f1 = (5, "some str", Bar1 {f :42});
-    foo(&f1);
-    let f2 = &f1;
-    foo(f2);
-    let f3: &Fat<dyn ToBar> = f2;
-    foo(f3);
-    let f4: &Fat<dyn ToBar> = &f1;
-    foo(f4);
-    let f5: &Fat<dyn ToBar> = &(5, "some str", Bar1 {f :42});
-    foo(f5);
-
-    // Zero size object.
-    let f6: &Fat<dyn ToBar> = &(5, "some str", Bar);
-    assert_eq!(f6.2.to_bar(), Bar);
-
-    // &*
-    //
-    let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42});
-    bar(&*f7);
-
-    // Deep nesting
-    let f1 = (5, "some str", (8, "deep str", Bar1 {f :42}));
-    baz(&f1);
-    let f2 = &f1;
-    baz(f2);
-    let f3: &Fat<Fat<dyn ToBar>> = f2;
-    baz(f3);
-    let f4: &Fat<Fat<dyn ToBar>> = &f1;
-    baz(f4);
-    let f5: &Fat<Fat<dyn ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42}));
-    baz(f5);
-}
diff --git a/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs b/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs
deleted file mode 100644
index ad48d88e480..00000000000
--- a/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-//@ run-pass
-
-#![feature(unsized_tuple_coercion)]
-
-// Ensure that unsizable fields that might be accessed don't get reordered
-
-fn nonzero_size() {
-    let sized: (u8, [u32; 2]) = (123, [456, 789]);
-    let unsize: &(u8, [u32]) = &sized;
-    assert_eq!(unsize.0, 123);
-    assert_eq!(unsize.1.len(), 2);
-    assert_eq!(unsize.1[0], 456);
-    assert_eq!(unsize.1[1], 789);
-}
-
-fn zst() {
-    let sized: (u8, [u32; 0]) = (123, []);
-    let unsize: &(u8, [u32]) = &sized;
-    assert_eq!(unsize.0, 123);
-    assert_eq!(unsize.1.len(), 0);
-}
-
-pub fn main() {
-    nonzero_size();
-    zst();
-}
diff --git a/tests/ui/dynamically-sized-types/dst-tuple-sole.rs b/tests/ui/dynamically-sized-types/dst-tuple-sole.rs
deleted file mode 100644
index dc3363b9bde..00000000000
--- a/tests/ui/dynamically-sized-types/dst-tuple-sole.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-//@ run-pass
-#![allow(stable_features)]
-#![allow(type_alias_bounds)]
-
-// As dst-tuple.rs, but the unsized field is the only field in the tuple.
-
-
-#![feature(unsized_tuple_coercion)]
-
-type Fat<T: ?Sized> = (T,);
-
-// x is a fat pointer
-fn foo(x: &Fat<[isize]>) {
-    let y = &x.0;
-    assert_eq!(x.0.len(), 3);
-    assert_eq!(y[0], 1);
-    assert_eq!(x.0[1], 2);
-}
-
-fn foo2<T:ToBar>(x: &Fat<[T]>) {
-    let y = &x.0;
-    let bar = Bar;
-    assert_eq!(x.0.len(), 3);
-    assert_eq!(y[0].to_bar(), bar);
-    assert_eq!(x.0[1].to_bar(), bar);
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-struct Bar;
-
-trait ToBar {
-    fn to_bar(&self) -> Bar;
-}
-
-impl ToBar for Bar {
-    fn to_bar(&self) -> Bar {
-        *self
-    }
-}
-
-pub fn main() {
-    // With a vec of ints.
-    let f1 = ([1, 2, 3],);
-    foo(&f1);
-    let f2 = &f1;
-    foo(f2);
-    let f3: &Fat<[isize]> = f2;
-    foo(f3);
-    let f4: &Fat<[isize]> = &f1;
-    foo(f4);
-    let f5: &Fat<[isize]> = &([1, 2, 3],);
-    foo(f5);
-
-    // With a vec of Bars.
-    let bar = Bar;
-    let f1 = ([bar, bar, bar],);
-    foo2(&f1);
-    let f2 = &f1;
-    foo2(f2);
-    let f3: &Fat<[Bar]> = f2;
-    foo2(f3);
-    let f4: &Fat<[Bar]> = &f1;
-    foo2(f4);
-    let f5: &Fat<[Bar]> = &([bar, bar, bar],);
-    foo2(f5);
-
-    // Assignment.
-    let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],);
-    f5.0[1] = 34;
-    assert_eq!(f5.0[0], 1);
-    assert_eq!(f5.0[1], 34);
-    assert_eq!(f5.0[2], 3);
-
-    // Zero size vec.
-    let f5: &Fat<[isize]> = &([],);
-    assert!(f5.0.is_empty());
-    let f5: &Fat<[Bar]> = &([],);
-    assert!(f5.0.is_empty());
-}
diff --git a/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs b/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs
deleted file mode 100644
index b4ee0fb4070..00000000000
--- a/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ run-pass
-
-#![feature(unsized_tuple_coercion)]
-
-// Check that we do not change the offsets of ZST fields when unsizing
-
-fn scalar_layout() {
-    let sized: &(u8, [(); 13]) = &(123, [(); 13]);
-    let unsize: &(u8, [()]) = sized;
-    assert_eq!(sized.1.as_ptr(), unsize.1.as_ptr());
-}
-
-fn scalarpair_layout() {
-    let sized: &(u8, u16, [(); 13]) = &(123, 456, [(); 13]);
-    let unsize: &(u8, u16, [()]) = sized;
-    assert_eq!(sized.2.as_ptr(), unsize.2.as_ptr());
-}
-
-pub fn main() {
-    scalar_layout();
-    scalarpair_layout();
-}
diff --git a/tests/ui/dynamically-sized-types/dst-tuple.rs b/tests/ui/dynamically-sized-types/dst-tuple.rs
deleted file mode 100644
index 52fc69f7809..00000000000
--- a/tests/ui/dynamically-sized-types/dst-tuple.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-//@ run-pass
-#![allow(type_alias_bounds)]
-
-#![feature(unsized_tuple_coercion)]
-
-type Fat<T: ?Sized> = (isize, &'static str, T);
-
-// x is a fat pointer
-fn foo(x: &Fat<[isize]>) {
-    let y = &x.2;
-    assert_eq!(x.2.len(), 3);
-    assert_eq!(y[0], 1);
-    assert_eq!(x.2[1], 2);
-    assert_eq!(x.0, 5);
-    assert_eq!(x.1, "some str");
-}
-
-fn foo2<T:ToBar>(x: &Fat<[T]>) {
-    let y = &x.2;
-    let bar = Bar;
-    assert_eq!(x.2.len(), 3);
-    assert_eq!(y[0].to_bar(), bar);
-    assert_eq!(x.2[1].to_bar(), bar);
-    assert_eq!(x.0, 5);
-    assert_eq!(x.1, "some str");
-}
-
-fn foo3(x: &Fat<Fat<[isize]>>) {
-    let y = &(x.2).2;
-    assert_eq!(x.0, 5);
-    assert_eq!(x.1, "some str");
-    assert_eq!((x.2).0, 8);
-    assert_eq!((x.2).1, "deep str");
-    assert_eq!((x.2).2.len(), 3);
-    assert_eq!(y[0], 1);
-    assert_eq!((x.2).2[1], 2);
-}
-
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-struct Bar;
-
-trait ToBar {
-    fn to_bar(&self) -> Bar;
-}
-
-impl ToBar for Bar {
-    fn to_bar(&self) -> Bar {
-        *self
-    }
-}
-
-pub fn main() {
-    // With a vec of ints.
-    let f1 = (5, "some str", [1, 2, 3]);
-    foo(&f1);
-    let f2 = &f1;
-    foo(f2);
-    let f3: &Fat<[isize]> = f2;
-    foo(f3);
-    let f4: &Fat<[isize]> = &f1;
-    foo(f4);
-    let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]);
-    foo(f5);
-
-    // With a vec of Bars.
-    let bar = Bar;
-    let f1 = (5, "some str", [bar, bar, bar]);
-    foo2(&f1);
-    let f2 = &f1;
-    foo2(f2);
-    let f3: &Fat<[Bar]> = f2;
-    foo2(f3);
-    let f4: &Fat<[Bar]> = &f1;
-    foo2(f4);
-    let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]);
-    foo2(f5);
-
-    // Assignment.
-    let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]);
-    f5.2[1] = 34;
-    assert_eq!(f5.2[0], 1);
-    assert_eq!(f5.2[1], 34);
-    assert_eq!(f5.2[2], 3);
-
-    // Zero size vec.
-    let f5: &Fat<[isize]> = &(5, "some str", []);
-    assert!(f5.2.is_empty());
-    let f5: &Fat<[Bar]> = &(5, "some str", []);
-    assert!(f5.2.is_empty());
-
-    // Deeply nested.
-    let f1 = (5, "some str", (8, "deep str", [1, 2, 3]));
-    foo3(&f1);
-    let f2 = &f1;
-    foo3(f2);
-    let f3: &Fat<Fat<[isize]>> = f2;
-    foo3(f3);
-    let f4: &Fat<Fat<[isize]>> = &f1;
-    foo3(f4);
-    let f5: &Fat<Fat<[isize]>> = &(5, "some str", (8, "deep str", [1, 2, 3]));
-    foo3(f5);
-
-    // Box.
-    let f1 = Box::new([1, 2, 3]);
-    assert_eq!((*f1)[1], 2);
-    let f2: Box<[isize]> = f1;
-    assert_eq!((*f2)[1], 2);
-
-    // Nested Box.
-    let f1 : Box<Fat<[isize; 3]>> = Box::new((5, "some str", [1, 2, 3]));
-    foo(&*f1);
-    let f2 : Box<Fat<[isize]>> = f1;
-    foo(&*f2);
-
-    let f3 : Box<Fat<[isize]>> =
-        Box::<Fat<[_; 3]>>::new((5, "some str", [1, 2, 3]));
-    foo(&*f3);
-}
diff --git a/tests/ui/error-codes/E0275.rs b/tests/ui/error-codes/E0275.rs
index df7b606155e..28a9676f03e 100644
--- a/tests/ui/error-codes/E0275.rs
+++ b/tests/ui/error-codes/E0275.rs
@@ -1,4 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
 trait Foo {}
 
 struct Bar<T>(T);
diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr
index b5075408340..3b31c87320a 100644
--- a/tests/ui/error-codes/E0275.stderr
+++ b/tests/ui/error-codes/E0275.stderr
@@ -1,12 +1,12 @@
 error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>: Foo`
-  --> $DIR/E0275.rs:6:33
+  --> $DIR/E0275.rs:5:33
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
 note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
-  --> $DIR/E0275.rs:6:9
+  --> $DIR/E0275.rs:5:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |         ^^^     ^               --- unsatisfied trait bound introduced here
diff --git a/tests/ui/error-codes/E0462.stderr b/tests/ui/error-codes/E0462.stderr
index 18f20d79385..be32001fad4 100644
--- a/tests/ui/error-codes/E0462.stderr
+++ b/tests/ui/error-codes/E0462.stderr
@@ -5,7 +5,7 @@ LL | extern crate found_staticlib;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the following crate versions were found:
-           crate `found_staticlib`: $TEST_BUILD_DIR/error-codes/E0462/auxiliary/libfound_staticlib.somelib
+           crate `found_staticlib`: $TEST_BUILD_DIR/auxiliary/libfound_staticlib.somelib
    = help: please recompile that crate using --crate-type lib
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0464.stderr b/tests/ui/error-codes/E0464.stderr
index edb0b1cf41e..ec18978a59a 100644
--- a/tests/ui/error-codes/E0464.stderr
+++ b/tests/ui/error-codes/E0464.stderr
@@ -4,9 +4,9 @@ error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
 LL | extern crate crateresolve1;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib
-   = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib
-   = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib
+   = note: candidate #1: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-1.somelib
+   = note: candidate #2: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-2.somelib
+   = note: candidate #3: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-3.somelib
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0523.stderr b/tests/ui/error-codes/E0523.stderr
index c6e65b55e2b..f4072d69104 100644
--- a/tests/ui/error-codes/E0523.stderr
+++ b/tests/ui/error-codes/E0523.stderr
@@ -4,9 +4,9 @@ error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
 LL | extern crate crateresolve1;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-1.somelib
-   = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-2.somelib
-   = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-3.somelib
+   = note: candidate #1: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-1.somelib
+   = note: candidate #2: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-2.somelib
+   = note: candidate #3: $TEST_BUILD_DIR/auxiliary/libcrateresolve1-3.somelib
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
index 64178e6f843..6f805aec1df 100644
--- a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
+++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
@@ -5,6 +5,7 @@ LL |         static symbol: [usize];
    |                        ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[usize]`
+   = note: statics and constants must have a statically known size
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
   --> $DIR/issue-36122-accessing-externed-dst.rs:5:20
diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
index d8dbd94696e..aa9c67f0151 100644
--- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
@@ -112,3 +112,14 @@ error: aborting due to 12 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0570, E0658.
 For more information about an error, try `rustc --explain E0570`.
+Future incompatibility report: Future breakage diagnostic:
+warning: the calling convention "gpu-kernel" is not supported on this target
+  --> $DIR/feature-gate-abi_gpu_kernel.rs:37:11
+   |
+LL | type A1 = extern "gpu-kernel" fn(_: ());
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
+   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default
+
diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs
index 171509876d1..1cf755b2c56 100644
--- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs
+++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs
@@ -1,8 +1,10 @@
 trait Trait {
+    #[type_const]
+    //~^ ERROR experimental
     const ASSOC: usize;
 }
 
-// FIXME(min_generic_const_args): implement support for this, behind the feature gate
+// FIXME(mgca): add suggestion for mgca to this error
 fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
     //~^ ERROR generic parameters may not be used in const operations
     loop {}
diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr
index 04d96b4c11e..af528a3c1b7 100644
--- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr
+++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/feature-gate-min-generic-const-args.rs:6:29
+  --> $DIR/feature-gate-min-generic-const-args.rs:8:29
    |
 LL | fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
    |                             ^ cannot perform const operation using `T`
@@ -7,5 +7,16 @@ LL | fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
    = note: type parameters may not be used in const expressions
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: aborting due to 1 previous error
+error[E0658]: the `#[type_const]` attribute is an experimental feature
+  --> $DIR/feature-gate-min-generic-const-args.rs:2:5
+   |
+LL |     #[type_const]
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
+   = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs
new file mode 100644
index 00000000000..ec49e53d9b4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs
@@ -0,0 +1,9 @@
+//@ only-elf
+//@ needs-dynamic-linking
+
+#[link(name = "meow", kind = "raw-dylib")] //~ ERROR: link kind `raw-dylib` is unstable on ELF platforms
+unsafe extern "C" {
+  safe fn meowmeow();
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr
new file mode 100644
index 00000000000..dfbf39f5a18
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr
@@ -0,0 +1,13 @@
+error[E0658]: link kind `raw-dylib` is unstable on ELF platforms
+  --> $DIR/feature-gate-raw-dylib-elf.rs:4:30
+   |
+LL | #[link(name = "meow", kind = "raw-dylib")]
+   |                              ^^^^^^^^^^^
+   |
+   = note: see issue #135694 <https://github.com/rust-lang/rust/issues/135694> for more information
+   = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
index c3d62a231e5..b5fbcc9ccf8 100644
--- a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
+++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _ : &(dyn Send,) = &((),);
-    //~^ ERROR unsized tuple coercion is not stable enough
+    //~^ ERROR 2:28: 2:34: mismatched types [E0308]
 }
diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
index 251928658df..12847bd3c0d 100644
--- a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
+++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
@@ -1,13 +1,14 @@
-error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change
+error[E0308]: mismatched types
   --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:28
    |
 LL |     let _ : &(dyn Send,) = &((),);
-   |                            ^^^^^^
+   |             ------------   ^^^^^^ expected `&(dyn Send,)`, found `&((),)`
+   |             |
+   |             expected due to this
    |
-   = note: see issue #42877 <https://github.com/rust-lang/rust/issues/42877> for more information
-   = help: add `#![feature(unsized_tuple_coercion)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: expected reference `&(dyn Send,)`
+              found reference `&((),)`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/feature-gates/feature-gate-where_clause_attrs.a.stderr b/tests/ui/feature-gates/feature-gate-where_clause_attrs.a.stderr
new file mode 100644
index 00000000000..6a8f01bbcce
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-where_clause_attrs.a.stderr
@@ -0,0 +1,883 @@
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:33:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:34:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:35:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:36:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:37:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:38:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:39:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:40:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:44:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:45:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:46:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:47:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:48:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:49:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:50:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:51:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:55:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:56:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:57:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:58:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:59:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:60:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:61:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:62:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:67:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:68:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:69:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:70:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:71:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:72:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:73:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:74:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:77:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:78:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:79:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:80:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:81:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:82:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:83:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:84:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:88:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:89:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:90:9
+   |
+LL |         #[cfg(all())] T: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:91:9
+   |
+LL |         #[cfg(any())] T: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:92:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:93:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:94:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:95:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:101:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:102:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:103:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:104:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:105:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:106:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:107:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:108:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:115:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:116:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:117:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:118:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:119:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:120:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:121:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:122:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:130:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:131:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:132:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:133:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:134:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:135:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:136:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:137:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:143:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:144:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:145:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:146:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:147:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:148:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:149:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:150:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:153:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:154:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:155:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:156:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:157:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:158:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:159:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:160:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 88 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-where_clause_attrs.b.stderr b/tests/ui/feature-gates/feature-gate-where_clause_attrs.b.stderr
new file mode 100644
index 00000000000..6a8f01bbcce
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-where_clause_attrs.b.stderr
@@ -0,0 +1,883 @@
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:33:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:34:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:35:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:36:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:37:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:38:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:39:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:40:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:44:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:45:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:46:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:47:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:48:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:49:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:50:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:51:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:55:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:56:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:57:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:58:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:59:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:60:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:61:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:62:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:67:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:68:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:69:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:70:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:71:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:72:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:73:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:74:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:77:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:78:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:79:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:80:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:81:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:82:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:83:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:84:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:88:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:89:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:90:9
+   |
+LL |         #[cfg(all())] T: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:91:9
+   |
+LL |         #[cfg(any())] T: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:92:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:93:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:94:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:95:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:101:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:102:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:103:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:104:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:105:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:106:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:107:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:108:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:115:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:116:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:117:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:118:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:119:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:120:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:121:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:122:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:130:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:131:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:132:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:133:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:134:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:135:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:136:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:137:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:143:5
+   |
+LL |     #[cfg(a)] T: TraitA,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:144:5
+   |
+LL |     #[cfg(b)] T: TraitB,
+   |     ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:145:5
+   |
+LL |     #[cfg(all())] T: TraitAll,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:146:5
+   |
+LL |     #[cfg(any())] T: TraitAny,
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:147:5
+   |
+LL |     #[cfg_attr(a, cfg(a))] T: TraitAA,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:148:5
+   |
+LL |     #[cfg_attr(b, cfg(b))] T: TraitBB,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:149:5
+   |
+LL |     #[cfg_attr(all(), cfg(all()))] T: TraitAllAll,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:150:5
+   |
+LL |     #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:153:9
+   |
+LL |         #[cfg(a)] U: TraitA,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:154:9
+   |
+LL |         #[cfg(b)] U: TraitB,
+   |         ^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:155:9
+   |
+LL |         #[cfg(all())] U: TraitAll,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:156:9
+   |
+LL |         #[cfg(any())] U: TraitAny,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:157:9
+   |
+LL |         #[cfg_attr(a, cfg(a))] U: TraitAA,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:158:9
+   |
+LL |         #[cfg_attr(b, cfg(b))] U: TraitBB,
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:159:9
+   |
+LL |         #[cfg_attr(all(), cfg(all()))] U: TraitAllAll,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: attributes in `where` clause are unstable
+  --> $DIR/feature-gate-where_clause_attrs.rs:160:9
+   |
+LL |         #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #115590 <https://github.com/rust-lang/rust/issues/115590> for more information
+   = help: add `#![feature(where_clause_attrs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 88 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-where_clause_attrs.rs b/tests/ui/feature-gates/feature-gate-where_clause_attrs.rs
new file mode 100644
index 00000000000..09c734a52de
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-where_clause_attrs.rs
@@ -0,0 +1,162 @@
+//@ revisions: a b
+
+#![crate_type = "lib"]
+use std::marker::PhantomData;
+
+#[cfg(a)]
+trait TraitA {}
+
+#[cfg(b)]
+trait TraitB {}
+
+#[cfg_attr(a, cfg(a))]
+trait TraitAA {}
+
+#[cfg_attr(b, cfg(b))]
+trait TraitBB {}
+
+#[cfg(all())]
+trait TraitAll {}
+
+#[cfg(any())]
+trait TraitAny {}
+
+#[cfg_attr(all(), cfg(all()))]
+trait TraitAllAll {}
+
+#[cfg_attr(any(), cfg(any()))]
+trait TraitAnyAny {}
+
+
+trait A<T>
+where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+    type B<U>
+    where
+        #[cfg(a)] U: TraitA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(b)] U: TraitB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(all())] U: TraitAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(any())] U: TraitAny, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(a, cfg(a))] U: TraitAA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(b, cfg(b))] U: TraitBB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(all(), cfg(all()))] U: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny; //~ ERROR attributes in `where` clause are unstable
+
+    fn foo<U>(&self)
+    where
+        #[cfg(a)] U: TraitA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(b)] U: TraitB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(all())] U: TraitAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(any())] U: TraitAny, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(a, cfg(a))] U: TraitAA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(b, cfg(b))] U: TraitBB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(all(), cfg(all()))] U: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny; //~ ERROR attributes in `where` clause are unstable
+}
+
+impl<T> A<T> for T
+where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+    type B<U> = () where
+        #[cfg(a)] U: TraitA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(b)] U: TraitB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(all())] U: TraitAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(any())] U: TraitAny, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(a, cfg(a))] U: TraitAA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(b, cfg(b))] U: TraitBB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(all(), cfg(all()))] U: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny; //~ ERROR attributes in `where` clause are unstable
+
+    fn foo<U>(&self)
+    where
+        #[cfg(a)] U: TraitA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(b)] U: TraitB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(a, cfg(a))] U: TraitAA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(b, cfg(b))] U: TraitBB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+    {}
+}
+
+struct C<T>
+where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+    _t: PhantomData<T>,
+}
+
+union D<T>
+where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+
+    _t: PhantomData<T>,
+}
+
+enum E<T>
+where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+    E(PhantomData<T>),
+}
+
+impl<T> C<T> where
+    #[cfg(a)] T: TraitA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(b)] T: TraitB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(all())] T: TraitAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg(any())] T: TraitAny, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(a, cfg(a))] T: TraitAA, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(b, cfg(b))] T: TraitBB, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(all(), cfg(all()))] T: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+    #[cfg_attr(any(), cfg(any()))] T: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+{
+    fn new<U>() where
+        #[cfg(a)] U: TraitA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(b)] U: TraitB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(all())] U: TraitAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg(any())] U: TraitAny, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(a, cfg(a))] U: TraitAA, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(b, cfg(b))] U: TraitBB, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(all(), cfg(all()))] U: TraitAllAll, //~ ERROR attributes in `where` clause are unstable
+        #[cfg_attr(any(), cfg(any()))] U: TraitAnyAny, //~ ERROR attributes in `where` clause are unstable
+    {}
+}
diff --git a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs
index 7b6ba9f7f16..e22a49d0399 100644
--- a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs
@@ -1,5 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
-
 fn id(
     f: &dyn Fn(u32),
 ) -> &dyn Fn(
diff --git a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
index be2eca3e61a..00a5948bdd4 100644
--- a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+  --> $DIR/hang-on-deeply-nested-dyn.rs:10:5
    |
 LL |   ) -> &dyn Fn(
    |  ______-
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
index f880749ec83..ff6f4861e14 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
@@ -1,5 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
-
 // rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T>`
 // should act as assertion that item does not borrow from its stream;
 // but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr
index ae364de8cc0..240e1c3dde1 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, {closure@hrtb-doesnt-borrow-self-1.rs:115:27}>`, but its trait bounds were not satisfied
-  --> $DIR/hrtb-doesnt-borrow-self-1.rs:116:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, {closure@hrtb-doesnt-borrow-self-1.rs:113:27}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:114:22
    |
 LL | pub struct Map<S, F> {
    | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt`
@@ -8,16 +8,16 @@ LL |     let filter = map.filterx(|x: &_| true);
    |                      ^^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
-      `&'a mut &Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
-      `&'a mut &mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
-      `&'a mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
-  --> $DIR/hrtb-doesnt-borrow-self-1.rs:98:50
+      `&'a mut &Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:113:27: 113:34}>: Stream`
+      `&'a mut &mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:113:27: 113:34}>: Stream`
+      `&'a mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:113:27: 113:34}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:96:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `StreamExt` defines an item `filterx`, perhaps you need to implement it
-  --> $DIR/hrtb-doesnt-borrow-self-1.rs:66:1
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:64:1
    |
 LL | pub trait StreamExt
    | ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
index ff4c0cf24d6..d8a1f3fa69e 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
@@ -1,5 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
-
 // rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
 // should act as assertion that item does not borrow from its stream;
 // but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
index eeb4e12fa8b..13041ea2bb0 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
@@ -1,5 +1,5 @@
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@hrtb-doesnt-borrow-self-2.rs:111:30}>`, but its trait bounds were not satisfied
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:112:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@hrtb-doesnt-borrow-self-2.rs:109:30}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:110:24
    |
 LL | pub struct Filter<S, F> {
    | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
@@ -8,16 +8,16 @@ LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
-      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
-      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:98:50
+      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
+      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:96:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `StreamExt` defines an item `countx`, perhaps you need to implement it
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:66:1
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:64:1
    |
 LL | pub trait StreamExt
    | ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
index 21e2fda1c3a..b9b551c1b23 100644
--- a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
@@ -8,8 +8,6 @@ trait Foo {
 
 impl Foo for () {
     fn bar() -> i32 {
-        //~^ ERROR method `bar` has an incompatible type for trait
-        //~| ERROR method `bar` has an incompatible return type for trait
         0
     }
 }
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
index d575fedbb58..24896151bed 100644
--- a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
@@ -11,7 +11,7 @@ LL |     fn bar() -> Wrapper<'static, impl Sized>;
    |                         ++++++++
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/opaque-and-lifetime-mismatch.rs:18:24
+  --> $DIR/opaque-and-lifetime-mismatch.rs:16:24
    |
 LL |     fn foo() -> Wrapper<impl Sized>;
    |                        ^ expected named lifetime parameter
@@ -23,7 +23,7 @@ LL |     fn foo() -> Wrapper<'static, impl Sized>;
    |                         ++++++++
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/opaque-and-lifetime-mismatch.rs:24:24
+  --> $DIR/opaque-and-lifetime-mismatch.rs:22:24
    |
 LL |     fn foo() -> Wrapper<impl Sized> {
    |                        ^ expected named lifetime parameter
@@ -49,7 +49,7 @@ LL | struct Wrapper<'rom>(&'rom ());
    |        ^^^^^^^
 
 error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/opaque-and-lifetime-mismatch.rs:18:17
+  --> $DIR/opaque-and-lifetime-mismatch.rs:16:17
    |
 LL |     fn foo() -> Wrapper<impl Sized>;
    |                 ^^^^^^^ ---------- help: remove the unnecessary generic argument
@@ -62,36 +62,8 @@ note: struct defined here, with 0 generic parameters
 LL | struct Wrapper<'rom>(&'rom ());
    |        ^^^^^^^
 
-error[E0053]: method `bar` has an incompatible return type for trait
-  --> $DIR/opaque-and-lifetime-mismatch.rs:10:17
-   |
-LL |     fn bar() -> i32 {
-   |                 ^^^
-   |                 |
-   |                 expected `Wrapper<'static>`, found `i32`
-   |                 return type in trait
-
-error[E0053]: method `bar` has an incompatible type for trait
-  --> $DIR/opaque-and-lifetime-mismatch.rs:10:17
-   |
-LL |     fn bar() -> i32 {
-   |                 ^^^ expected `Wrapper<'static>`, found `i32`
-   |
-note: type in trait
-  --> $DIR/opaque-and-lifetime-mismatch.rs:4:17
-   |
-LL |     fn bar() -> Wrapper<impl Sized>;
-   |                 ^^^^^^^^^^^^^^^^^^^
-   = note: expected signature `fn() -> Wrapper<'static>`
-              found signature `fn() -> i32`
-help: change the output type to match the trait
-   |
-LL -     fn bar() -> i32 {
-LL +     fn bar() -> Wrapper<'static> {
-   |
-
 error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/opaque-and-lifetime-mismatch.rs:24:17
+  --> $DIR/opaque-and-lifetime-mismatch.rs:22:17
    |
 LL |     fn foo() -> Wrapper<impl Sized> {
    |                 ^^^^^^^ ---------- help: remove the unnecessary generic argument
@@ -104,7 +76,7 @@ note: struct defined here, with 0 generic parameters
 LL | struct Wrapper<'rom>(&'rom ());
    |        ^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0053, E0106, E0107.
-For more information about an error, try `rustc --explain E0053`.
+Some errors have detailed explanations: E0106, E0107.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr
index 4198095db65..73e7890f91f 100644
--- a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr
+++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr
@@ -75,7 +75,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/opaque-used-in-extraneous-argument.rs:20:5
    |
 LL |     open_parent(&old_path)
-   |     ^^^^^^^^^^^ --------- unexpected argument of type `&impl Fn<{type error}> + FnOnce<{type error}, Output = {type error}> + 'static`
+   |     ^^^^^^^^^^^ --------- unexpected argument of type `&impl Fn<{type error}> + FnOnce<{type error}, Output = {type error}> + '_`
    |
 note: function defined here
   --> $DIR/opaque-used-in-extraneous-argument.rs:12:4
diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs
index 161fe23c899..8e30973cd3a 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs
+++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs
@@ -1,6 +1,5 @@
 fn no_elided_lt() -> impl Sized + use<'_> {}
 //~^ ERROR missing lifetime specifier
-//~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_`
 
 fn static_lt() -> impl Sized + use<'static> {}
 //~^ ERROR expected lifetime parameter in `use<...>` precise captures list, found `'static`
diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr
index c8dac3a69cd..98f629f52cf 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr
@@ -12,26 +12,20 @@ LL + fn no_elided_lt() -> impl Sized + use<'static> {}
    |
 
 error[E0261]: use of undeclared lifetime name `'missing`
-  --> $DIR/bad-lifetimes.rs:8:37
+  --> $DIR/bad-lifetimes.rs:7:37
    |
 LL | fn missing_lt() -> impl Sized + use<'missing> {}
    |              -                      ^^^^^^^^ undeclared lifetime
    |              |
    |              help: consider introducing lifetime `'missing` here: `<'missing>`
 
-error: expected lifetime parameter in `use<...>` precise captures list, found `'_`
-  --> $DIR/bad-lifetimes.rs:1:39
-   |
-LL | fn no_elided_lt() -> impl Sized + use<'_> {}
-   |                                       ^^
-
 error: expected lifetime parameter in `use<...>` precise captures list, found `'static`
-  --> $DIR/bad-lifetimes.rs:5:36
+  --> $DIR/bad-lifetimes.rs:4:36
    |
 LL | fn static_lt() -> impl Sized + use<'static> {}
    |                                    ^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0106, E0261.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs
deleted file mode 100644
index 2678564f0e8..00000000000
--- a/tests/ui/impl-trait/unsize_tuple.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//! Test that we allow unsizing `([Opaque; N],)` to `([Concrete],)`.
-
-//@check-pass
-
-#![feature(unsized_tuple_coercion)]
-
-fn hello() -> ([impl Sized; 2],) {
-    if false {
-        let x = hello();
-        let _: &([i32],) = &x;
-    }
-    todo!()
-}
-
-fn main() {}
diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs
index 6e126575aa9..5822c5474bd 100644
--- a/tests/ui/implied-bounds/from-trait-impl.rs
+++ b/tests/ui/implied-bounds/from-trait-impl.rs
@@ -12,6 +12,7 @@ where
 
 fn func1(foo: Foo<(&str,)>) {
     //~^ ERROR `&str` does not fulfill the required lifetime
+    //~| ERROR lifetime may not live long enough
     let _: &'static str = foo.0.0;
 }
 
@@ -19,5 +20,6 @@ trait TestTrait {}
 
 impl<X> TestTrait for [Foo<(X,)>; 1] {}
 //~^ ERROR `X` may not live long enough
+//~| ERROR `X` may not live long enough
 
 fn main() {}
diff --git a/tests/ui/implied-bounds/from-trait-impl.stderr b/tests/ui/implied-bounds/from-trait-impl.stderr
index 4151d206ae2..5f189d3385a 100644
--- a/tests/ui/implied-bounds/from-trait-impl.stderr
+++ b/tests/ui/implied-bounds/from-trait-impl.stderr
@@ -7,7 +7,21 @@ LL | fn func1(foo: Foo<(&str,)>) {
    = note: type must satisfy the static lifetime
 
 error[E0310]: the parameter type `X` may not live long enough
-  --> $DIR/from-trait-impl.rs:20:23
+  --> $DIR/from-trait-impl.rs:21:1
+   |
+LL | impl<X> TestTrait for [Foo<(X,)>; 1] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | the parameter type `X` must be valid for the static lifetime...
+   | ...so that the type `X` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | impl<X: 'static> TestTrait for [Foo<(X,)>; 1] {}
+   |       +++++++++
+
+error[E0310]: the parameter type `X` may not live long enough
+  --> $DIR/from-trait-impl.rs:21:23
    |
 LL | impl<X> TestTrait for [Foo<(X,)>; 1] {}
    |                       ^^^^^^^^^^^^^^
@@ -20,7 +34,16 @@ help: consider adding an explicit lifetime bound
 LL | impl<X: 'static> TestTrait for [Foo<(X,)>; 1] {}
    |       +++++++++
 
-error: aborting due to 2 previous errors
+error: lifetime may not live long enough
+  --> $DIR/from-trait-impl.rs:13:1
+   |
+LL | fn func1(foo: Foo<(&str,)>) {
+   | ^^^^^^^^^^^^^^^^^^^-^^^^^^^
+   | |                  |
+   | |                  let's call the lifetime of this reference `'1`
+   | requires that `'1` must outlive `'static`
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0310, E0477.
 For more information about an error, try `rustc --explain E0310`.
diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr
deleted file mode 100644
index c43cc0999f1..00000000000
--- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/normalization-nested.rs:40:5
-   |
-LL | pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
-   |                      -- lifetime `'x` defined here
-LL |     s
-   |     ^ returning this value requires that `'x` must outlive `'static`
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs
index 4527e33a291..9a0defd1667 100644
--- a/tests/ui/implied-bounds/normalization-nested.rs
+++ b/tests/ui/implied-bounds/normalization-nested.rs
@@ -3,9 +3,7 @@
 //
 //@ revisions: param_ty lifetime param_ty_no_compat lifetime_no_compat
 
-//@[param_ty] check-pass
-//@[param_ty_no_compat] check-pass
-//@[lifetime_no_compat] check-pass
+//@ check-pass
 //@[param_ty_no_compat] compile-flags: -Zno-implied-bounds-compat
 //@[lifetime_no_compat] compile-flags: -Zno-implied-bounds-compat
 
@@ -38,7 +36,6 @@ pub fn test_wfcheck<'x>(_: Map<Vec<&'x ()>>) {}
 
 pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
     s
-    //[lifetime]~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr b/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr
index a591d0f5d4d..8919919d04e 100644
--- a/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr
+++ b/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr
@@ -1,15 +1,45 @@
 error[E0477]: the type `&'lt u8` does not fulfill the required lifetime
+  --> $DIR/normalization-placeholder-leak.rs:31:5
+   |
+LL |     fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0477]: the type `&'lt u8` does not fulfill the required lifetime
   --> $DIR/normalization-placeholder-leak.rs:31:40
    |
 LL |     fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {}
    |                                        ^^^^^^^^^^^^
 
 error[E0477]: the type `<T as AnotherTrait>::Ty2<'lt>` does not fulfill the required lifetime
-  --> $DIR/normalization-placeholder-leak.rs:36:44
+  --> $DIR/normalization-placeholder-leak.rs:38:5
+   |
+LL |     fn test_alias<'lt, T: AnotherTrait>(_: Foo<T::Ty2::<'lt>>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0477]: the type `<T as AnotherTrait>::Ty2<'lt>` does not fulfill the required lifetime
+  --> $DIR/normalization-placeholder-leak.rs:38:44
    |
 LL |     fn test_alias<'lt, T: AnotherTrait>(_: Foo<T::Ty2::<'lt>>) {}
    |                                            ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: lifetime may not live long enough
+  --> $DIR/normalization-placeholder-leak.rs:31:5
+   |
+LL |     fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {}
+   |     ^^^^^^^^^^^^^^^^^---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                |
+   |     |                lifetime `'lt` defined here
+   |     requires that `'lt` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-placeholder-leak.rs:38:5
+   |
+LL |     fn test_alias<'lt, T: AnotherTrait>(_: Foo<T::Ty2::<'lt>>) {}
+   |     ^^^^^^^^^^^^^^---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |             |
+   |     |             lifetime `'lt` defined here
+   |     requires that `'lt` must outlive `'static`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0477`.
diff --git a/tests/ui/implied-bounds/normalization-placeholder-leak.rs b/tests/ui/implied-bounds/normalization-placeholder-leak.rs
index a9dfa69cfd6..3a15897db82 100644
--- a/tests/ui/implied-bounds/normalization-placeholder-leak.rs
+++ b/tests/ui/implied-bounds/normalization-placeholder-leak.rs
@@ -30,11 +30,15 @@ mod fail {
     // don't use the bound to prove `'lt: 'static`.
     fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {}
     //[fail]~^ ERROR `&'lt u8` does not fulfill the required lifetime
+    //[fail]~| ERROR `&'lt u8` does not fulfill the required lifetime
+    //[fail]~| ERROR may not live long enough
 
     // implied bound: `T::Ty2<'lt>: placeholder('x)`.
     // don't use the bound to prove `T::Ty2<'lt>: 'static`.
     fn test_alias<'lt, T: AnotherTrait>(_: Foo<T::Ty2::<'lt>>) {}
     //[fail]~^ ERROR `<T as AnotherTrait>::Ty2<'lt>` does not fulfill the required lifetime
+    //[fail]~| ERROR `<T as AnotherTrait>::Ty2<'lt>` does not fulfill the required lifetime
+    //[fail]~| ERROR may not live long enough
 }
 
 
diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs
index 7443a29f30c..032483e1be4 100644
--- a/tests/ui/implied-bounds/sod_service_chain.rs
+++ b/tests/ui/implied-bounds/sod_service_chain.rs
@@ -27,11 +27,19 @@ pub struct ServiceChainBuilder<P: Service, S: Service<Input = P::Output>> {
 }
 impl<P: Service, S: Service<Input = P::Output>> ServiceChainBuilder<P, S> {
     pub fn next<NS: Service<Input = S::Output>>(
+        //~^ the associated type
+        //~| the associated type
+        //~| the associated type
+        //~| the associated type
+        //~| the associated type
+        //~| the associated type
+        //~| may not live long enough
         self,
     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
         //~^ the associated type
         //~| the associated type
         //~| the associated type
+        //~| the associated type
         panic!();
     }
 }
diff --git a/tests/ui/implied-bounds/sod_service_chain.stderr b/tests/ui/implied-bounds/sod_service_chain.stderr
index 1c0ef573e7d..f5221fc1105 100644
--- a/tests/ui/implied-bounds/sod_service_chain.stderr
+++ b/tests/ui/implied-bounds/sod_service_chain.stderr
@@ -1,5 +1,39 @@
 error[E0310]: the associated type `<P as Service>::Error` may not live long enough
-  --> $DIR/sod_service_chain.rs:31:10
+  --> $DIR/sod_service_chain.rs:29:5
+   |
+LL | /     pub fn next<NS: Service<Input = S::Output>>(
+...  |
+LL | |         self,
+LL | |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
+   | |                                                    ^
+   | |                                                    |
+   | |____________________________________________________the associated type `<P as Service>::Error` must be valid for the static lifetime...
+   |                                                      ...so that the type `<P as Service>::Error` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <P as Service>::Error: 'static {
+   |                                                      ++++++++++++++++++++++++++++++++++++
+
+error[E0310]: the associated type `<S as Service>::Error` may not live long enough
+  --> $DIR/sod_service_chain.rs:29:5
+   |
+LL | /     pub fn next<NS: Service<Input = S::Output>>(
+...  |
+LL | |         self,
+LL | |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
+   | |                                                    ^
+   | |                                                    |
+   | |____________________________________________________the associated type `<S as Service>::Error` must be valid for the static lifetime...
+   |                                                      ...so that the type `<S as Service>::Error` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <S as Service>::Error: 'static {
+   |                                                      ++++++++++++++++++++++++++++++++++++
+
+error[E0310]: the associated type `<P as Service>::Error` may not live long enough
+  --> $DIR/sod_service_chain.rs:38:10
    |
 LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +47,7 @@ LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <P as Service>::
    |                                                      ++++++++++++++++++++++++++++++++++++
 
 error[E0310]: the associated type `<S as Service>::Error` may not live long enough
-  --> $DIR/sod_service_chain.rs:31:10
+  --> $DIR/sod_service_chain.rs:38:10
    |
 LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,6 +60,42 @@ help: consider adding an explicit lifetime bound
 LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <S as Service>::Error: 'static {
    |                                                      ++++++++++++++++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error[E0310]: the associated type `<P as Service>::Error` may not live long enough
+  --> $DIR/sod_service_chain.rs:29:5
+   |
+LL | /     pub fn next<NS: Service<Input = S::Output>>(
+...  |
+LL | |         self,
+LL | |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
+   | |                                                    ^
+   | |                                                    |
+   | |____________________________________________________the associated type `<P as Service>::Error` must be valid for the static lifetime...
+   |                                                      ...so that the type `<P as Service>::Error` will meet its required lifetime bounds
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding an explicit lifetime bound
+   |
+LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <P as Service>::Error: 'static {
+   |                                                      ++++++++++++++++++++++++++++++++++++
+
+error[E0310]: the associated type `<S as Service>::Error` may not live long enough
+  --> $DIR/sod_service_chain.rs:29:5
+   |
+LL | /     pub fn next<NS: Service<Input = S::Output>>(
+...  |
+LL | |         self,
+LL | |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
+   | |                                                    ^
+   | |                                                    |
+   | |____________________________________________________the associated type `<S as Service>::Error` must be valid for the static lifetime...
+   |                                                      ...so that the type `<S as Service>::Error` will meet its required lifetime bounds
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding an explicit lifetime bound
+   |
+LL |     ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> where <S as Service>::Error: 'static {
+   |                                                      ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
index 62fc079d9d9..e28b8f373da 100644
--- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
+++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
@@ -3,9 +3,6 @@
 //@ error-pattern: reached the recursion limit while instantiating
 //@ error-pattern: reached the recursion limit finding the struct tail
 
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
-
 // Regression test for #114484: This used to ICE during monomorphization, because we treated
 // `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion
 // limit when finding the struct tail.
diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
index b67e000bf74..475e26fd0f0 100644
--- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
+++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
@@ -18,7 +18,7 @@ error: reached the recursion limit finding the struct tail for `[u8; 256]`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ error: reached the recursion limit finding the struct tail for `SomeData<256>`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ error: reached the recursion limit finding the struct tail for `VirtualWrapper<S
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,11 +76,11 @@ LL |         unsafe { virtualize_my_trait(L, self) }
 error: reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<..., 1>, 1>, 1>, 1>, 1> as MyTrait>::virtualize`
    |
 note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:28:5
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:5
    |
 LL |     fn virtualize(&self) -> &dyn MyTrait {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/infinite-instantiation-struct-tail-ice-114484.long-type.txt'
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/infinite/infinite-instantiation.rs b/tests/ui/infinite/infinite-instantiation.rs
index d5cb8e79592..7898cc1ffc1 100644
--- a/tests/ui/infinite/infinite-instantiation.rs
+++ b/tests/ui/infinite/infinite-instantiation.rs
@@ -1,6 +1,4 @@
 //@ build-fail
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 trait ToOpt: Sized {
     fn to_option(&self) -> Option<Self>;
diff --git a/tests/ui/infinite/infinite-instantiation.stderr b/tests/ui/infinite/infinite-instantiation.stderr
index 71c745cf5eb..d7a4a49961a 100644
--- a/tests/ui/infinite/infinite-instantiation.stderr
+++ b/tests/ui/infinite/infinite-instantiation.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `function::<Option<Option<Option<Option<Option<...>>>>>>`
-  --> $DIR/infinite-instantiation.rs:23:9
+  --> $DIR/infinite-instantiation.rs:21:9
    |
 LL |         function(counter - 1, t.to_option());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `function` defined here
-  --> $DIR/infinite-instantiation.rs:21:1
+  --> $DIR/infinite-instantiation.rs:19:1
    |
 LL | fn function<T:ToOpt + Clone>(counter: usize, t: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/infinite-instantiation.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr
index a18d2779cad..05d42247d41 100644
--- a/tests/ui/invalid-compile-flags/print-without-arg.stderr
+++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr
@@ -1,5 +1,5 @@
 error: Argument to option 'print' missing
        Usage:
-           --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target]
+           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                                Compiler information to print on stdout
 
diff --git a/tests/ui/issues/issue-13497.rs b/tests/ui/issues/issue-13497.rs
index 7f786a54b9f..4b2795aa841 100644
--- a/tests/ui/issues/issue-13497.rs
+++ b/tests/ui/issues/issue-13497.rs
@@ -3,7 +3,6 @@ fn read_lines_borrowed1() -> Vec<
 > {
     let rawLines: Vec<String> = vec!["foo  ".to_string(), "  bar".to_string()];
     rawLines.iter().map(|l| l.trim()).collect()
-    //~^ ERROR: cannot return value referencing
 }
 
 fn main() {}
diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr
index 8016b55d6aa..ee111f1d262 100644
--- a/tests/ui/issues/issue-13497.stderr
+++ b/tests/ui/issues/issue-13497.stderr
@@ -15,16 +15,6 @@ LL -     &str
 LL +     String
    |
 
-error[E0515]: cannot return value referencing local variable `rawLines`
-  --> $DIR/issue-13497.rs:5:5
-   |
-LL |     rawLines.iter().map(|l| l.trim()).collect()
-   |     --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     returns a value referencing data owned by the current function
-   |     `rawLines` is borrowed here
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0106, E0515.
-For more information about an error, try `rustc --explain E0106`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/issues/issue-20413.rs b/tests/ui/issues/issue-20413.rs
index 7766f375599..138a235e675 100644
--- a/tests/ui/issues/issue-20413.rs
+++ b/tests/ui/issues/issue-20413.rs
@@ -1,4 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
 trait Foo {
     fn answer(self);
 }
diff --git a/tests/ui/issues/issue-20413.stderr b/tests/ui/issues/issue-20413.stderr
index 5d442eb9898..42f3cd2d062 100644
--- a/tests/ui/issues/issue-20413.stderr
+++ b/tests/ui/issues/issue-20413.stderr
@@ -1,5 +1,5 @@
 error[E0392]: type parameter `T` is never used
-  --> $DIR/issue-20413.rs:6:15
+  --> $DIR/issue-20413.rs:5:15
    |
 LL | struct NoData<T>;
    |               ^ unused type parameter
@@ -8,14 +8,14 @@ LL | struct NoData<T>;
    = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
 
 error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>: Foo`
-  --> $DIR/issue-20413.rs:9:36
+  --> $DIR/issue-20413.rs:8:36
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
 note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
-  --> $DIR/issue-20413.rs:9:9
+  --> $DIR/issue-20413.rs:8:9
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
    |         ^^^     ^                  --- unsatisfied trait bound introduced here
@@ -23,19 +23,19 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    = note: required for `NoData<T>` to implement `Foo`
 
 error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>: Bar`
-  --> $DIR/issue-20413.rs:28:42
+  --> $DIR/issue-20413.rs:27:42
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
 note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
-  --> $DIR/issue-20413.rs:35:9
+  --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
 note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
-  --> $DIR/issue-20413.rs:28:9
+  --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
@@ -43,19 +43,19 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    = note: required for `EvenLessData<T>` to implement `Baz`
 
 error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>: Baz`
-  --> $DIR/issue-20413.rs:35:42
+  --> $DIR/issue-20413.rs:34:42
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
 note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
-  --> $DIR/issue-20413.rs:28:9
+  --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
 note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
-  --> $DIR/issue-20413.rs:35:9
+  --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
index ebaf244ac9c..05adde45204 100644
--- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
+++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
@@ -1,6 +1,4 @@
 //@ build-fail
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 trait Mirror {
     type Image;
diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
index fbbf80021be..945fa605e14 100644
--- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
+++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `<(&(&(..., ...), ...), ...) as Foo>::recurse`
-  --> $DIR/issue-37311.rs:18:9
+  --> $DIR/issue-37311.rs:16:9
    |
 LL |         (self, self).recurse();
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `<T as Foo>::recurse` defined here
-  --> $DIR/issue-37311.rs:17:5
+  --> $DIR/issue-37311.rs:15:5
    |
 LL |     fn recurse(&self) {
    |     ^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/issue-37311.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr
index 97e5990750e..2cd5a2a49ef 100644
--- a/tests/ui/issues/issue-54410.stderr
+++ b/tests/ui/issues/issue-54410.stderr
@@ -5,6 +5,7 @@ LL |     pub static mut symbol: [i8];
    |                            ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[i8]`
+   = note: statics and constants must have a statically known size
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-67552.rs b/tests/ui/issues/issue-67552.rs
index 8c7e95bd2e3..53f0e931d60 100644
--- a/tests/ui/issues/issue-67552.rs
+++ b/tests/ui/issues/issue-67552.rs
@@ -1,7 +1,5 @@
 //@ build-fail
 //@ compile-flags: -Copt-level=0
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 fn main() {
     rec(Empty);
diff --git a/tests/ui/issues/issue-67552.stderr b/tests/ui/issues/issue-67552.stderr
index f94cd78c870..def0a29f3e5 100644
--- a/tests/ui/issues/issue-67552.stderr
+++ b/tests/ui/issues/issue-67552.stderr
@@ -1,17 +1,17 @@
 error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut ...>`
-  --> $DIR/issue-67552.rs:30:9
+  --> $DIR/issue-67552.rs:28:9
    |
 LL |         rec(identity(&mut it))
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `rec` defined here
-  --> $DIR/issue-67552.rs:23:1
+  --> $DIR/issue-67552.rs:21:1
    |
 LL | / fn rec<T>(mut it: T)
 LL | | where
 LL | |     T: Iterator,
    | |________________^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/issue-67552.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-8727.rs b/tests/ui/issues/issue-8727.rs
index 7767729109e..1883287f140 100644
--- a/tests/ui/issues/issue-8727.rs
+++ b/tests/ui/issues/issue-8727.rs
@@ -2,8 +2,6 @@
 // recursions.
 
 //@ build-fail
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 fn generic<T>() { //~ WARN function cannot return without recursing
     generic::<Option<T>>();
diff --git a/tests/ui/issues/issue-8727.stderr b/tests/ui/issues/issue-8727.stderr
index 22286eb8d7b..04158962a01 100644
--- a/tests/ui/issues/issue-8727.stderr
+++ b/tests/ui/issues/issue-8727.stderr
@@ -1,5 +1,5 @@
 warning: function cannot return without recursing
-  --> $DIR/issue-8727.rs:8:1
+  --> $DIR/issue-8727.rs:6:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^ cannot return without recursing
@@ -10,17 +10,17 @@ LL |     generic::<Option<T>>();
    = note: `#[warn(unconditional_recursion)]` on by default
 
 error: reached the recursion limit while instantiating `generic::<Option<Option<Option<Option<Option<...>>>>>>`
-  --> $DIR/issue-8727.rs:9:5
+  --> $DIR/issue-8727.rs:7:5
    |
 LL |     generic::<Option<T>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `generic` defined here
-  --> $DIR/issue-8727.rs:8:1
+  --> $DIR/issue-8727.rs:6:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/issue-8727.long-type.txt'
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/json/json-multiple.stderr b/tests/ui/json/json-multiple.stderr
index 7689fb94a6c..e285817cffb 100644
--- a/tests/ui/json/json-multiple.stderr
+++ b/tests/ui/json/json-multiple.stderr
@@ -1 +1 @@
-{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/json/json-multiple/libjson_multiple.rlib","emit":"link"}
+{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/libjson_multiple.rlib","emit":"link"}
diff --git a/tests/ui/json/json-options.stderr b/tests/ui/json/json-options.stderr
index 668fc18097f..fff4ec9a6df 100644
--- a/tests/ui/json/json-options.stderr
+++ b/tests/ui/json/json-options.stderr
@@ -1 +1 @@
-{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/json/json-options/libjson_options.rlib","emit":"link"}
+{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/libjson_options.rlib","emit":"link"}
diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr
index 8ddce285e23..e296abfc3b5 100644
--- a/tests/ui/layout/issue-84108.stderr
+++ b/tests/ui/layout/issue-84108.stderr
@@ -30,6 +30,15 @@ LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:15:13
+   |
+LL | static BAZ: ([u8], usize) = ([], 0);
+   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/issue-84108.rs:9:12
    |
 LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
@@ -56,15 +65,6 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: only the last element of a tuple may have a dynamically sized type
-
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:15:13
-   |
-LL | static BAZ: ([u8], usize) = ([], 0);
-   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-   = note: only the last element of a tuple may have a dynamically sized type
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/lifetimes/issue-26638.rs b/tests/ui/lifetimes/issue-26638.rs
index 11c730165f2..e73cf21bd6c 100644
--- a/tests/ui/lifetimes/issue-26638.rs
+++ b/tests/ui/lifetimes/issue-26638.rs
@@ -3,7 +3,6 @@ fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next()
 
 fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
 //~^ ERROR missing lifetime specifier [E0106]
-//~| ERROR mismatched types
 //~| ERROR function takes 1 argument but 0 arguments were supplied
 
 fn parse_type_3() -> &str { unimplemented!() }
diff --git a/tests/ui/lifetimes/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr
index bdf91136765..74a1676f684 100644
--- a/tests/ui/lifetimes/issue-26638.stderr
+++ b/tests/ui/lifetimes/issue-26638.stderr
@@ -32,7 +32,7 @@ LL + fn parse_type_2(iter: fn(&u8)->&u8) -> String { iter() }
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:9:22
+  --> $DIR/issue-26638.rs:8:22
    |
 LL | fn parse_type_3() -> &str { unimplemented!() }
    |                      ^ expected named lifetime parameter
@@ -59,18 +59,7 @@ help: provide the argument
 LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter(/* &u8 */) }
    |                                                    +++++++++
 
-error[E0308]: mismatched types
-  --> $DIR/issue-26638.rs:4:47
-   |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-   |                                        ----   ^^^^^^ expected `&str`, found `&u8`
-   |                                        |
-   |                                        expected `&'static str` because of return type
-   |
-   = note: expected reference `&'static str`
-              found reference `&u8`
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0061, E0106, E0308.
+Some errors have detailed explanations: E0061, E0106.
 For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs
new file mode 100644
index 00000000000..f4715ff2d3d
--- /dev/null
+++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs
@@ -0,0 +1,37 @@
+//@ only-elf
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+
+//@ revisions: with without
+
+//@ [without] build-fail
+//@ [without] regex-error-pattern:error: linking with `.*` failed
+//@ [without] dont-check-compiler-stderr
+
+//@ [with] build-pass
+
+//! Ensures that linking fails when there's an undefined symbol,
+//! and that it does succeed with raw-dylib.
+
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))]
+#[cfg_attr(without, link(name = "rawdylibbutforcats"))]
+unsafe extern "C" {
+  safe fn meooooooooooooooow();
+}
+
+
+#[cfg_attr(with, link(name = "rawdylibbutfordogs", kind = "raw-dylib"))]
+#[cfg_attr(without, link(name = "rawdylibbutfordogs"))]
+unsafe extern "C" {
+  safe fn woooooooooooooooooof();
+}
+
+fn main() {
+  meooooooooooooooow();
+  woooooooooooooooooof();
+}
diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs
new file mode 100644
index 00000000000..fe9c7884e54
--- /dev/null
+++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs
@@ -0,0 +1,28 @@
+//@ only-elf
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+//@ revisions: with without
+
+//@ [without] build-fail
+//@ [without] regex-error-pattern:error: linking with `.*` failed
+//@ [without] dont-check-compiler-stderr
+
+//@ [with] build-pass
+
+//! Ensures that linking fails when there's an undefined symbol,
+//! and that it does succeed with raw-dylib.
+
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))]
+#[cfg_attr(without, link(name = "rawdylibbutforcats"))]
+unsafe extern "C" {
+  safe fn meooooooooooooooow();
+}
+
+fn main() {
+  meooooooooooooooow();
+}
diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs
new file mode 100644
index 00000000000..72cba18d841
--- /dev/null
+++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs
@@ -0,0 +1,29 @@
+//@ only-elf
+//@ needs-dynamic-linking
+// FIXME(raw_dylib_elf): Debug the failures on other targets.
+//@ only-gnu
+//@ only-x86_64
+
+//@ revisions: with without
+
+//@ [without] build-fail
+//@ [without] regex-error-pattern:error: linking with `.*` failed
+//@ [without] dont-check-compiler-stderr
+
+//@ [with] build-pass
+
+//! Ensures that linking fails when there's an undefined symbol,
+//! and that it does succeed with raw-dylib, but with verbatim.
+
+#![feature(raw_dylib_elf)]
+#![allow(incomplete_features)]
+
+#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib", modifiers = "+verbatim"))]
+#[cfg_attr(without, link(name = "rawdylibbutforcats", modifiers = "+verbatim"))]
+unsafe extern "C" {
+  safe fn meooooooooooooooow();
+}
+
+fn main() {
+  meooooooooooooooow();
+}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
index e69a4537935..e69a4537935 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr
index 90cca83d1c1..90cca83d1c1 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
index 50ad8a173ad..50ad8a173ad 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
index d2cf7a0ba1f..d2cf7a0ba1f 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
index cf456b9b261..cf456b9b261 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
index 8e65baf65df..8e65baf65df 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
index b3859ba1ce6..b3859ba1ce6 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
index 4b8b90eb6e2..4b8b90eb6e2 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
index 3ead5cb1fd7..3ead5cb1fd7 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
index 75cadc471c4..75cadc471c4 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
index ab0dcda64e6..ab0dcda64e6 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
index 757f1f7994e..757f1f7994e 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs
index 057242246f0..057242246f0 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr
index 4bbad9b30a7..4bbad9b30a7 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs
index b04c2facbcd..b04c2facbcd 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr
index f1e54d37827..f1e54d37827 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs
index 9b7e8d70743..9b7e8d70743 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr
index 6341e57a0be..6341e57a0be 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs
index 6b8cd49566d..6b8cd49566d 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr
index 1b04bb228e7..1b04bb228e7 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs
index f5fb1649cdc..f5fb1649cdc 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr
index 2e6cf3761c2..2e6cf3761c2 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
index 5982c771033..5982c771033 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr
index 8f279508720..8f279508720 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs
index 9d741630fc9..9d741630fc9 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr
index 811145e77ee..811145e77ee 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs
index 9988115fd8b..9988115fd8b 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr
index d5ce8aff34f..d5ce8aff34f 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs
index 14e915d602a..14e915d602a 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr
index 200b8f62874..200b8f62874 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs
index bf3c5e4d435..bf3c5e4d435 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr
index b766b5c8dd8..b766b5c8dd8 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr
new file mode 100644
index 00000000000..70945ed6fc0
--- /dev/null
+++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr
@@ -0,0 +1,13 @@
+error[E0658]: link kind `raw-dylib` is unstable on ELF platforms
+  --> $DIR/raw-dylib-windows-only.rs:6:29
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   |                             ^^^^^^^^^^^
+   |
+   = note: see issue #135694 <https://github.com/rust-lang/rust/issues/135694> for more information
+   = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr
index ede20cb8c3f..daed15d784a 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr
@@ -1,5 +1,5 @@
 error[E0455]: link kind `raw-dylib` is only supported on Windows targets
-  --> $DIR/raw-dylib-windows-only.rs:3:29
+  --> $DIR/raw-dylib-windows-only.rs:6:29
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
    |                             ^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs
new file mode 100644
index 00000000000..935c59b5aaa
--- /dev/null
+++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs
@@ -0,0 +1,9 @@
+//@ revisions: elf notelf
+//@ [elf] only-elf
+//@ [notelf] ignore-windows
+//@ [notelf] ignore-elf
+//@ compile-flags: --crate-type lib
+#[link(name = "foo", kind = "raw-dylib")]
+//[notelf]~^ ERROR: link kind `raw-dylib` is only supported on Windows targets
+//[elf]~^^ ERROR: link kind `raw-dylib` is unstable on ELF platforms
+extern "C" {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs
index 48af6b009d3..48af6b009d3 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr
index ef022404e7f..ef022404e7f 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr
diff --git a/tests/ui/lint/removed-lints/README.md b/tests/ui/lint/removed-lints/README.md
new file mode 100644
index 00000000000..abe7ee04115
--- /dev/null
+++ b/tests/ui/lint/removed-lints/README.md
@@ -0,0 +1,4 @@
+# Removed lints
+
+This directory contains tests to confirm that lints that have been
+removed do not cause errors and produce the appropriate warnings.
diff --git a/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.rs b/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.rs
new file mode 100644
index 00000000000..7fb635487ff
--- /dev/null
+++ b/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.rs
@@ -0,0 +1,5 @@
+//@ check-pass
+
+#![deny(ptr_cast_add_auto_to_object)]
+//~^ WARN  lint `ptr_cast_add_auto_to_object` has been removed
+fn main() {}
diff --git a/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.stderr b/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.stderr
new file mode 100644
index 00000000000..36b5e847d80
--- /dev/null
+++ b/tests/ui/lint/removed-lints/ptr_cast_add_auto_to_object.stderr
@@ -0,0 +1,10 @@
+warning: lint `ptr_cast_add_auto_to_object` has been removed: converted into hard error, see issue #127323 <https://github.com/rust-lang/rust/issues/127323> for more information
+  --> $DIR/ptr_cast_add_auto_to_object.rs:3:9
+   |
+LL | #![deny(ptr_cast_add_auto_to_object)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/methods/inherent-bound-in-probe.rs b/tests/ui/methods/inherent-bound-in-probe.rs
index 9b9eb91559b..4add93e808d 100644
--- a/tests/ui/methods/inherent-bound-in-probe.rs
+++ b/tests/ui/methods/inherent-bound-in-probe.rs
@@ -1,5 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
-
 // Fixes #110131
 //
 // The issue is that we were constructing an `ImplDerived` cause code for the
diff --git a/tests/ui/methods/inherent-bound-in-probe.stderr b/tests/ui/methods/inherent-bound-in-probe.stderr
index 433ef02a2aa..77aed390c9a 100644
--- a/tests/ui/methods/inherent-bound-in-probe.stderr
+++ b/tests/ui/methods/inherent-bound-in-probe.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Helper<'a, T>` is not an iterator
-  --> $DIR/inherent-bound-in-probe.rs:40:21
+  --> $DIR/inherent-bound-in-probe.rs:38:21
    |
 LL |     type IntoIter = Helper<'a, T>;
    |                     ^^^^^^^^^^^^^ `Helper<'a, T>` is not an iterator
@@ -9,14 +9,14 @@ note: required by a bound in `std::iter::IntoIterator::IntoIter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
 
 error[E0275]: overflow evaluating the requirement `&_: IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:44:9
+  --> $DIR/inherent-bound-in-probe.rs:42:9
    |
 LL |         Helper::new(&self.0)
    |         ^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_bound_in_probe`)
 note: required for `&BitReaderWrapper<_>` to implement `IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:34:13
+  --> $DIR/inherent-bound-in-probe.rs:32:13
    |
 LL | impl<'a, T> IntoIterator for &'a BitReaderWrapper<T>
    |             ^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     &'a T: IntoIterator<Item = &'a u8>,
    = note: 126 redundant requirements hidden
    = note: required for `&BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `IntoIterator`
 note: required by a bound in `Helper`
-  --> $DIR/inherent-bound-in-probe.rs:18:12
+  --> $DIR/inherent-bound-in-probe.rs:16:12
    |
 LL | struct Helper<'a, T>
    |        ------ required by a bound in this struct
diff --git a/tests/ui/parser/bounds-lifetime-where.rs b/tests/ui/parser/bounds-lifetime-where.rs
index 7ff75233d3a..730be7139be 100644
--- a/tests/ui/parser/bounds-lifetime-where.rs
+++ b/tests/ui/parser/bounds-lifetime-where.rs
@@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK
 type A where 'a: 'b + 'c = u8; // OK
 type A where = u8; // OK
 type A where 'a: 'b + = u8; // OK
-type A where , = u8; //~ ERROR expected one of `;`, `=`, `where`, lifetime, or type, found `,`
+type A where , = u8; //~ ERROR expected one of `#`, `;`, `=`, `where`, lifetime, or type, found `,`
 
 fn main() {}
diff --git a/tests/ui/parser/bounds-lifetime-where.stderr b/tests/ui/parser/bounds-lifetime-where.stderr
index 9dd963afc79..5aadb5fff32 100644
--- a/tests/ui/parser/bounds-lifetime-where.stderr
+++ b/tests/ui/parser/bounds-lifetime-where.stderr
@@ -1,8 +1,8 @@
-error: expected one of `;`, `=`, `where`, lifetime, or type, found `,`
+error: expected one of `#`, `;`, `=`, `where`, lifetime, or type, found `,`
   --> $DIR/bounds-lifetime-where.rs:8:14
    |
 LL | type A where , = u8;
-   |              ^ expected one of `;`, `=`, `where`, lifetime, or type
+   |              ^ expected one of `#`, `;`, `=`, `where`, lifetime, or type
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr
index 196a46d7ea5..6245f81d533 100644
--- a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr
+++ b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr
@@ -2,7 +2,7 @@ error: return type should be specified after the function parameters
   --> $DIR/misplaced-return-type-where-in-next-line-issue-126311.rs:5:15
    |
 LL |     K: Clone, -> Result<u8, String>
-   |               ^^ expected one of `{`, lifetime, or type
+   |               ^^ expected one of `#`, `{`, lifetime, or type
    |
 help: place the return type after the function parameters
    |
diff --git a/tests/ui/parser/ranges-precedence.rs b/tests/ui/parser/ranges-precedence.rs
index 14dd6488ff2..783799f7099 100644
--- a/tests/ui/parser/ranges-precedence.rs
+++ b/tests/ui/parser/ranges-precedence.rs
@@ -1,7 +1,8 @@
 //@ run-pass
+//@ edition: 2021
 // Test that the precedence of ranges is correct
 
-
+use core::ops::{Add, RangeTo};
 
 struct Foo {
     foo: usize,
@@ -11,6 +12,13 @@ impl Foo {
     fn bar(&self) -> usize { 5 }
 }
 
+impl Add<RangeTo<usize>> for Foo {
+    type Output = usize;
+    fn add(self, range: RangeTo<usize>) -> Self::Output {
+        self.foo + range.end
+    }
+}
+
 fn main() {
     let x = 1+3..4+5;
     assert_eq!(x, (4..9));
@@ -49,4 +57,22 @@ fn main() {
 
     let y = ..;
     assert_eq!(y, (..));
+
+    let reference = &..0;
+    assert_eq!(*reference, ..0);
+    let reference2 = &&..0;
+    assert_eq!(**reference2, ..0);
+
+    let closure = || ..0;
+    assert_eq!(closure(), ..0);
+
+    let sum = Foo { foo: 3 } + ..4;
+    assert_eq!(sum, 7);
+
+    macro_rules! expr {
+        ($e:expr) => {};
+    }
+    expr!(!..0);
+    expr!(-..0);
+    expr!(*..0);
 }
diff --git a/tests/ui/recursion/issue-23122-2.rs b/tests/ui/recursion/issue-23122-2.rs
index 3e14fa92dd0..95e1f60d8b0 100644
--- a/tests/ui/recursion/issue-23122-2.rs
+++ b/tests/ui/recursion/issue-23122-2.rs
@@ -1,4 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
 trait Next {
     type Next: Next;
 }
diff --git a/tests/ui/recursion/issue-23122-2.stderr b/tests/ui/recursion/issue-23122-2.stderr
index 10463ab2c33..c5774cc1888 100644
--- a/tests/ui/recursion/issue-23122-2.stderr
+++ b/tests/ui/recursion/issue-23122-2.stderr
@@ -1,12 +1,12 @@
 error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:11:17
+  --> $DIR/issue-23122-2.rs:10:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
 note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
-  --> $DIR/issue-23122-2.rs:10:15
+  --> $DIR/issue-23122-2.rs:9:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |      -        ^^^^     ^^^^^^^^^^
diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs
index ea1bef4fce3..b720c168187 100644
--- a/tests/ui/recursion/issue-83150.rs
+++ b/tests/ui/recursion/issue-83150.rs
@@ -1,7 +1,6 @@
-//~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator`
+//~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
 //@ build-fail
 //@ compile-flags: -Copt-level=0
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
 
 fn main() {
     let mut iter = 0u8..1;
diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr
index 92a39a44e4f..600922f1e57 100644
--- a/tests/ui/recursion/issue-83150.stderr
+++ b/tests/ui/recursion/issue-83150.stderr
@@ -1,5 +1,5 @@
 warning: function cannot return without recursing
-  --> $DIR/issue-83150.rs:11:1
+  --> $DIR/issue-83150.rs:10:1
    |
 LL | fn func<T: Iterator<Item = u8>>(iter: &mut T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -10,12 +10,12 @@ LL |     func(&mut iter.map(|x| x + 1))
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator`
+error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
    = note: 65 redundant requirements hidden
-   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/recursion/recursion.rs b/tests/ui/recursion/recursion.rs
index ce56fe974b7..5cd4012a9d2 100644
--- a/tests/ui/recursion/recursion.rs
+++ b/tests/ui/recursion/recursion.rs
@@ -1,7 +1,5 @@
 //@ build-fail
 //@ compile-flags:-C overflow-checks=off
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 enum Nil {NilValue}
 struct Cons<T> {head:isize, tail:T}
diff --git a/tests/ui/recursion/recursion.stderr b/tests/ui/recursion/recursion.stderr
index cb9f67ba741..f959805defc 100644
--- a/tests/ui/recursion/recursion.stderr
+++ b/tests/ui/recursion/recursion.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>`
-  --> $DIR/recursion.rs:19:11
+  --> $DIR/recursion.rs:17:11
    |
 LL |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `test` defined here
-  --> $DIR/recursion.rs:17:1
+  --> $DIR/recursion.rs:15:1
    |
 LL | fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/recursion.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/regions/issue-102374.rs b/tests/ui/regions/issue-102374.rs
index d640c29b2f4..e0a1164211a 100644
--- a/tests/ui/regions/issue-102374.rs
+++ b/tests/ui/regions/issue-102374.rs
@@ -1,4 +1,3 @@
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
 use std::cell::Cell;
 
 #[rustfmt::skip]
diff --git a/tests/ui/regions/issue-102374.stderr b/tests/ui/regions/issue-102374.stderr
index e07dca0c7ee..5416125d1c7 100644
--- a/tests/ui/regions/issue-102374.stderr
+++ b/tests/ui/regions/issue-102374.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102374.rs:17:5
+  --> $DIR/issue-102374.rs:16:5
    |
 LL | ) -> i32 {
    |      --- expected `i32` because of return type
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
deleted file mode 100644
index 3b982857db8..00000000000
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ ignore-windows
-//@ compile-flags: --crate-type lib
-#[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets
-extern "C" {}
diff --git a/tests/ui/rmeta/emit-artifact-notifications.stderr b/tests/ui/rmeta/emit-artifact-notifications.stderr
index 4f68a2d74ed..c002be7bcff 100644
--- a/tests/ui/rmeta/emit-artifact-notifications.stderr
+++ b/tests/ui/rmeta/emit-artifact-notifications.stderr
@@ -1 +1 @@
-{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"}
+{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/libemit_artifact_notifications.rmeta","emit":"metadata"}
diff --git a/tests/ui/simd/intrinsic/generic-gather.rs b/tests/ui/simd/intrinsic/generic-gather.rs
new file mode 100644
index 00000000000..118d8029483
--- /dev/null
+++ b/tests/ui/simd/intrinsic/generic-gather.rs
@@ -0,0 +1,52 @@
+//@ build-fail
+//@ ignore-emscripten
+
+// Test that the simd_{gather,scatter} intrinsics produce ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, core_intrinsics)]
+#![allow(non_camel_case_types)]
+
+use std::intrinsics::simd::{simd_gather, simd_scatter};
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct x4<T>(pub [T; 4]);
+
+fn main() {
+    let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
+
+    let default = x4([-3_f32, -3., -3., -3.]);
+    let s_strided = x4([0_f32, 2., -3., 6.]);
+
+    let mask = x4([-1_i32, -1, 0, -1]);
+    let umask = x4([0u16; 4]);
+    let fmask = x4([0_f32; 4]);
+
+    let pointer = x.as_mut_ptr();
+    let pointers =
+        unsafe { x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]) };
+
+    unsafe {
+        simd_gather(default, mask, mask);
+        //~^ ERROR expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32`
+
+        simd_gather(default, pointers, umask);
+        //~^ ERROR expected element type `u16` of third argument `x4<u16>` to be a signed integer type
+
+        simd_gather(default, pointers, fmask);
+        //~^ ERROR expected element type `f32` of third argument `x4<f32>` to be a signed integer type
+    }
+
+    unsafe {
+        let values = x4([42_f32, 43_f32, 44_f32, 45_f32]);
+        simd_scatter(values, mask, mask);
+        //~^ ERROR expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*mut f32`
+
+        simd_scatter(values, pointers, umask);
+        //~^ ERROR expected element type `u16` of third argument `x4<u16>` to be a signed integer type
+
+        simd_scatter(values, pointers, fmask);
+        //~^ ERROR expected element type `f32` of third argument `x4<f32>` to be a signed integer type
+    }
+}
diff --git a/tests/ui/simd/intrinsic/generic-gather.stderr b/tests/ui/simd/intrinsic/generic-gather.stderr
new file mode 100644
index 00000000000..81e10fc9875
--- /dev/null
+++ b/tests/ui/simd/intrinsic/generic-gather.stderr
@@ -0,0 +1,39 @@
+error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*_ f32`
+  --> $DIR/generic-gather.rs:31:9
+   |
+LL |         simd_gather(default, mask, mask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `u16` of third argument `x4<u16>` to be a signed integer type
+  --> $DIR/generic-gather.rs:34:9
+   |
+LL |         simd_gather(default, pointers, umask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `f32` of third argument `x4<f32>` to be a signed integer type
+  --> $DIR/generic-gather.rs:37:9
+   |
+LL |         simd_gather(default, pointers, fmask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*mut f32`
+  --> $DIR/generic-gather.rs:43:9
+   |
+LL |         simd_scatter(values, mask, mask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `u16` of third argument `x4<u16>` to be a signed integer type
+  --> $DIR/generic-gather.rs:46:9
+   |
+LL |         simd_scatter(values, pointers, umask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `f32` of third argument `x4<f32>` to be a signed integer type
+  --> $DIR/generic-gather.rs:49:9
+   |
+LL |         simd_scatter(values, pointers, fmask);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/tests/ui/simd/intrinsic/generic-select.rs b/tests/ui/simd/intrinsic/generic-select.rs
index 917ad3ca604..db14032f1f2 100644
--- a/tests/ui/simd/intrinsic/generic-select.rs
+++ b/tests/ui/simd/intrinsic/generic-select.rs
@@ -37,10 +37,10 @@ fn main() {
         //~^ ERROR mismatched lengths: mask length `8` != other vector length `4`
 
         simd_select(x, x, x);
-        //~^ ERROR mask element type is `u32`, expected `i_`
+        //~^ ERROR mask element type is `u32`, expected a signed integer type
 
         simd_select(z, z, z);
-        //~^ ERROR mask element type is `f32`, expected `i_`
+        //~^ ERROR mask element type is `f32`, expected a signed integer type
 
         simd_select(m4, 0u32, 1u32);
         //~^ ERROR found non-SIMD `u32`
diff --git a/tests/ui/simd/intrinsic/generic-select.stderr b/tests/ui/simd/intrinsic/generic-select.stderr
index c46584d117c..b9af86515fd 100644
--- a/tests/ui/simd/intrinsic/generic-select.stderr
+++ b/tests/ui/simd/intrinsic/generic-select.stderr
@@ -4,17 +4,21 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched le
 LL |         simd_select(m8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: found mask element type is `u32`, expected a signed integer type
   --> $DIR/generic-select.rs:39:9
    |
 LL |         simd_select(x, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the mask may be widened, which only has the correct behavior for signed integers
 
-error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: found mask element type is `f32`, expected a signed integer type
   --> $DIR/generic-select.rs:42:9
    |
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the mask may be widened, which only has the correct behavior for signed integers
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
   --> $DIR/generic-select.rs:45:9
diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr
index 033caf07d8e..0e6e338c5ef 100644
--- a/tests/ui/static/issue-24446.stderr
+++ b/tests/ui/static/issue-24446.stderr
@@ -14,6 +14,7 @@ LL |     static foo: dyn Fn() -> u32 = || -> u32 {
    |                 ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
+   = note: statics and constants must have a statically known size
 
 error[E0308]: mismatched types
   --> $DIR/issue-24446.rs:2:35
diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr
index ffbbe218c87..3f9b0879c16 100644
--- a/tests/ui/statics/unsized_type2.stderr
+++ b/tests/ui/statics/unsized_type2.stderr
@@ -10,6 +10,7 @@ note: required because it appears within the type `Foo`
    |
 LL | pub struct Foo {
    |            ^^^
+   = note: statics and constants must have a statically known size
 
 error[E0308]: mismatched types
   --> $DIR/unsized_type2.rs:14:45
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index 9b1568fa116..dbc9e7d254c 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -8,8 +8,8 @@ ast-stats-1 ExprField                 48 ( 0.7%)             1            48
 ast-stats-1 Attribute                 64 ( 1.0%)             2            32
 ast-stats-1 - DocComment                32 ( 0.5%)             1
 ast-stats-1 - Normal                    32 ( 0.5%)             1
-ast-stats-1 WherePredicate            64 ( 1.0%)             1            64
-ast-stats-1 - BoundPredicate            64 ( 1.0%)             1
+ast-stats-1 WherePredicate            72 ( 1.1%)             1            72
+ast-stats-1 - BoundPredicate            72 ( 1.1%)             1
 ast-stats-1 Local                     80 ( 1.2%)             1            80
 ast-stats-1 ForeignItem               88 ( 1.3%)             1            88
 ast-stats-1 - Fn                        88 ( 1.3%)             1
@@ -37,14 +37,14 @@ ast-stats-1 Expr                     576 ( 8.6%)             8            72
 ast-stats-1 - Match                     72 ( 1.1%)             1
 ast-stats-1 - Path                      72 ( 1.1%)             1
 ast-stats-1 - Struct                    72 ( 1.1%)             1
-ast-stats-1 - Lit                      144 ( 2.2%)             2
+ast-stats-1 - Lit                      144 ( 2.1%)             2
 ast-stats-1 - Block                    216 ( 3.2%)             3
 ast-stats-1 PathSegment              744 (11.1%)            31            24
 ast-stats-1 Ty                       896 (13.4%)            14            64
 ast-stats-1 - Ptr                       64 ( 1.0%)             1
 ast-stats-1 - Ref                       64 ( 1.0%)             1
 ast-stats-1 - ImplicitSelf             128 ( 1.9%)             2
-ast-stats-1 - Path                     640 ( 9.6%)            10
+ast-stats-1 - Path                     640 ( 9.5%)            10
 ast-stats-1 Item                   1_224 (18.3%)             9           136
 ast-stats-1 - Enum                     136 ( 2.0%)             1
 ast-stats-1 - ForeignMod               136 ( 2.0%)             1
@@ -53,7 +53,7 @@ ast-stats-1 - Trait                    136 ( 2.0%)             1
 ast-stats-1 - Fn                       272 ( 4.1%)             2
 ast-stats-1 - Use                      408 ( 6.1%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_696                   116
+ast-stats-1 Total                  6_704                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -62,8 +62,8 @@ ast-stats-2 Crate                     40 ( 0.5%)             1            40
 ast-stats-2 GenericArgs               40 ( 0.5%)             1            40
 ast-stats-2 - AngleBracketed            40 ( 0.5%)             1
 ast-stats-2 ExprField                 48 ( 0.7%)             1            48
-ast-stats-2 WherePredicate            64 ( 0.9%)             1            64
-ast-stats-2 - BoundPredicate            64 ( 0.9%)             1
+ast-stats-2 WherePredicate            72 ( 1.0%)             1            72
+ast-stats-2 - BoundPredicate            72 ( 1.0%)             1
 ast-stats-2 Local                     80 ( 1.1%)             1            80
 ast-stats-2 ForeignItem               88 ( 1.2%)             1            88
 ast-stats-2 - Fn                        88 ( 1.2%)             1
@@ -104,16 +104,16 @@ ast-stats-2 - Ptr                       64 ( 0.9%)             1
 ast-stats-2 - Ref                       64 ( 0.9%)             1
 ast-stats-2 - ImplicitSelf             128 ( 1.7%)             2
 ast-stats-2 - Path                     640 ( 8.7%)            10
-ast-stats-2 Item                   1_496 (20.4%)            11           136
-ast-stats-2 - Enum                     136 ( 1.9%)             1
-ast-stats-2 - ExternCrate              136 ( 1.9%)             1
-ast-stats-2 - ForeignMod               136 ( 1.9%)             1
-ast-stats-2 - Impl                     136 ( 1.9%)             1
-ast-stats-2 - Trait                    136 ( 1.9%)             1
+ast-stats-2 Item                   1_496 (20.3%)            11           136
+ast-stats-2 - Enum                     136 ( 1.8%)             1
+ast-stats-2 - ExternCrate              136 ( 1.8%)             1
+ast-stats-2 - ForeignMod               136 ( 1.8%)             1
+ast-stats-2 - Impl                     136 ( 1.8%)             1
+ast-stats-2 - Trait                    136 ( 1.8%)             1
 ast-stats-2 - Fn                       272 ( 3.7%)             2
 ast-stats-2 - Use                      544 ( 7.4%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_344                   127
+ast-stats-2 Total                  7_352                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs
index 71d90ddd935..ba99b03539c 100644
--- a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs
+++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs
@@ -1,5 +1,5 @@
 #![feature(default_field_values)]
-struct A<'a> { //~ ERROR lifetime parameter `'a` is never used
+struct A<'a> {
     x: Vec<A> = Vec::new(), //~ ERROR missing lifetime specifier
 }
 
diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr
index 20b9afe80cd..7100efc695c 100644
--- a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr
+++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr
@@ -9,15 +9,6 @@ help: consider using the `'a` lifetime
 LL |     x: Vec<A<'a>> = Vec::new(),
    |             ++++
 
-error[E0392]: lifetime parameter `'a` is never used
-  --> $DIR/do-not-ice-on-invalid-lifetime.rs:2:10
-   |
-LL | struct A<'a> {
-   |          ^^ unused lifetime parameter
-   |
-   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0106, E0392.
-For more information about an error, try `rustc --explain E0106`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs
index 0ac071d91d6..1e94eecb4f8 100644
--- a/tests/ui/structs/default-field-values/failures.rs
+++ b/tests/ui/structs/default-field-values/failures.rs
@@ -17,9 +17,9 @@ pub struct Bar {
 
 #[derive(Default)]
 pub struct Qux<const C: i32> {
-    bar: S = Self::S, //~ ERROR generic `Self` types are currently not permitted in anonymous constants
+    bar: S = Self::S,
     baz: i32 = foo(),
-    bat: i32 = <Qux<{ C }> as T>::K, //~ ERROR generic parameters may not be used in const operations
+    bat: i32 = <Qux<{ C }> as T>::K,
     bay: i32 = C,
 }
 
diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr
index 65ec100fe2e..50553816462 100644
--- a/tests/ui/structs/default-field-values/failures.stderr
+++ b/tests/ui/structs/default-field-values/failures.stderr
@@ -6,27 +6,12 @@ LL |     Variant {}
    |
    = help: consider a manual implementation of `Default`
 
-error: generic parameters may not be used in const operations
-  --> $DIR/failures.rs:22:23
-   |
-LL |     bat: i32 = <Qux<{ C }> as T>::K,
-   |                       ^ cannot perform const operation using `C`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `C`
-   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
-
 error: default fields are not supported in tuple structs
   --> $DIR/failures.rs:26:22
    |
 LL | pub struct Rak(i32 = 42);
    |                      ^^ default fields are only supported on structs
 
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/failures.rs:20:14
-   |
-LL |     bar: S = Self::S,
-   |              ^^^^
-
 error[E0277]: the trait bound `S: Default` is not satisfied
   --> $DIR/failures.rs:14:5
    |
@@ -112,7 +97,7 @@ LL -     let _ = Rak(.., 0);
 LL +     let _ = Rak(0);
    |
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0061, E0277, E0308.
 For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/structs/default-field-values/field-references-param.rs b/tests/ui/structs/default-field-values/field-references-param.rs
new file mode 100644
index 00000000000..ecee37edd42
--- /dev/null
+++ b/tests/ui/structs/default-field-values/field-references-param.rs
@@ -0,0 +1,29 @@
+//@ build-pass
+
+#![feature(default_field_values)]
+
+struct W<const X: usize>;
+
+impl<const X: usize> W<X> {
+    const fn new() -> Self { W }
+}
+
+struct Z<const X: usize> {
+    // No inference.
+    one: W<X> = W::<X>::new(),
+
+    // Inference works too.
+    two: W<X> = W::new(),
+
+    // An anon const that is too generic before substitution.
+    too_generic: usize = X + 1,
+}
+
+fn use_generically<const X: usize>() {
+    let x: Z<X> = Z { .. };
+}
+
+fn main() {
+    let x: Z<0> = Z { .. };
+    use_generically::<0>();
+}
diff --git a/tests/ui/structs/default-field-values/post-mono.direct.stderr b/tests/ui/structs/default-field-values/post-mono.direct.stderr
new file mode 100644
index 00000000000..cdd80620c48
--- /dev/null
+++ b/tests/ui/structs/default-field-values/post-mono.direct.stderr
@@ -0,0 +1,23 @@
+error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
+  --> $DIR/post-mono.rs:7:24
+   |
+LL |     post_mono: usize = X / 0,
+   |                        ^^^^^ attempt to divide `1_usize` by zero
+
+note: erroneous constant encountered
+  --> $DIR/post-mono.rs:17:19
+   |
+LL |     let x: Z<1> = Z { .. };
+   |                   ^^^^^^^^
+
+note: erroneous constant encountered
+  --> $DIR/post-mono.rs:17:19
+   |
+LL |     let x: Z<1> = Z { .. };
+   |                   ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/structs/default-field-values/post-mono.indirect.stderr b/tests/ui/structs/default-field-values/post-mono.indirect.stderr
new file mode 100644
index 00000000000..56c27a6e5dc
--- /dev/null
+++ b/tests/ui/structs/default-field-values/post-mono.indirect.stderr
@@ -0,0 +1,29 @@
+error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
+  --> $DIR/post-mono.rs:7:24
+   |
+LL |     post_mono: usize = X / 0,
+   |                        ^^^^^ attempt to divide `1_usize` by zero
+
+note: erroneous constant encountered
+  --> $DIR/post-mono.rs:12:19
+   |
+LL |     let x: Z<X> = Z { .. };
+   |                   ^^^^^^^^
+
+note: erroneous constant encountered
+  --> $DIR/post-mono.rs:12:19
+   |
+LL |     let x: Z<X> = Z { .. };
+   |                   ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+note: the above error was encountered while instantiating `fn indirect::<1>`
+  --> $DIR/post-mono.rs:22:5
+   |
+LL |     indirect::<1>();
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs
new file mode 100644
index 00000000000..4de31f6e2fb
--- /dev/null
+++ b/tests/ui/structs/default-field-values/post-mono.rs
@@ -0,0 +1,23 @@
+//@ build-fail
+//@ revisions: direct indirect
+
+#![feature(default_field_values)]
+
+struct Z<const X: usize> {
+    post_mono: usize = X / 0,
+    //~^ ERROR evaluation of `Z::<1>::post_mono::{constant#0}` failed
+}
+
+fn indirect<const X: usize>() {
+    let x: Z<X> = Z { .. };
+}
+
+#[cfg(direct)]
+fn main() {
+    let x: Z<1> = Z { .. };
+}
+
+#[cfg(indirect)]
+fn main() {
+    indirect::<1>();
+}
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
index daec66709b6..443a7e3835e 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
@@ -18,7 +18,6 @@ mod elided {
     // But that lifetime does not participate in resolution.
     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
     //~^ ERROR missing lifetime specifier
-    //~| ERROR lifetime may not live long enough
 }
 
 mod underscore {
@@ -37,7 +36,6 @@ mod underscore {
     // But that lifetime does not participate in resolution.
     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
     //~^ ERROR missing lifetime specifier
-    //~| ERROR lifetime may not live long enough
 }
 
 mod alone_in_path {
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
index 204209179ad..24013c85c87 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -41,7 +41,7 @@ LL +     async fn i(mut x: impl Iterator<Item = &()>) -> Option<()> { x.next() }
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:28:58
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58
    |
 LL |     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
    |                                                          ^^ expected named lifetime parameter
@@ -64,7 +64,7 @@ LL +     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:38:64
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
    |
 LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
    |                                                                ^^ expected named lifetime parameter
@@ -87,7 +87,7 @@ LL +     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next(
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:49:37
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
    |
 LL |     fn g(mut x: impl Foo) -> Option<&()> { x.next() }
    |                                     ^ expected named lifetime parameter
@@ -108,7 +108,7 @@ LL +     fn g(mut x: impl Foo) -> Option<()> { x.next() }
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:60:41
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:58:41
    |
 LL |     fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
    |                                         ^ expected named lifetime parameter
@@ -129,7 +129,7 @@ LL +     fn g(mut x: impl Foo<()>) -> Option<()> { x.next() }
    |
 
 warning: elided lifetime has a name
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:66:57
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:64:57
    |
 LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) {
    |                       -- lifetime `'a` declared here    ^ this elided lifetime gets resolved as `'a`
@@ -162,16 +162,8 @@ help: consider introducing a named lifetime parameter
 LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&()> { x.next() }
    |         ++++                              ++
 
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67
-   |
-LL |     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
-   |     -----------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   |     |
-   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
-
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:25:35
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:24:35
    |
 LL |     fn f(_: impl Iterator<Item = &'_ ()>) {}
    |                                   ^^ expected named lifetime parameter
@@ -185,7 +177,7 @@ LL +     fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
    |
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:28:39
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:27:39
    |
 LL |     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
    |                                       ^^ expected named lifetime parameter
@@ -198,16 +190,8 @@ LL -     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next()
 LL +     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'_ ()> { x.next() }
    |
 
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73
-   |
-LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |     -----------------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   |     |
-   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
-
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:46:18
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:44:18
    |
 LL |     fn f(_: impl Foo) {}
    |                  ^^^ expected named lifetime parameter
@@ -220,7 +204,7 @@ LL |     fn f<'a>(_: impl Foo<'a>) {}
    |         ++++            ++++
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:49:22
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:47:22
    |
 LL |     fn g(mut x: impl Foo) -> Option<&()> { x.next() }
    |                      ^^^ expected named lifetime parameter
@@ -233,7 +217,7 @@ LL |     fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
    |         ++++                ++++
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:57:22
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
    |
 LL |     fn f(_: impl Foo<()>) {}
    |                      ^ expected named lifetime parameter
@@ -246,7 +230,7 @@ LL |     fn f<'a>(_: impl Foo<'a, ()>) {}
    |         ++++             +++
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:60:26
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
    |
 LL |     fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
    |                          ^ expected named lifetime parameter
@@ -258,7 +242,7 @@ help: consider introducing a named lifetime parameter
 LL |     fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
    |         ++++                 +++
 
-error: aborting due to 16 previous errors; 1 warning emitted
+error: aborting due to 14 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0106, E0658.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs
index 12dc0e8216b..27f03431d09 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime.rs
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs
@@ -8,7 +8,6 @@ fn f(_: impl Iterator<Item = &'_ ()>) {}
 // But that lifetime does not participate in resolution.
 fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
 //~^ ERROR missing lifetime specifier
-//~| ERROR lifetime may not live long enough
 
 // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
 async fn h(_: impl Iterator<Item = &'_ ()>) {}
@@ -16,6 +15,5 @@ async fn h(_: impl Iterator<Item = &'_ ()>) {}
 // But that lifetime does not participate in resolution.
 async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
 //~^ ERROR missing lifetime specifier
-//~| ERROR lifetime may not live long enough
 
 fn main() {}
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
index dfbc883680b..c09c575c147 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
@@ -22,7 +22,7 @@ LL + fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime.rs:17:60
+  --> $DIR/impl-trait-missing-lifetime.rs:16:60
    |
 LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
    |                                                            ^^ expected named lifetime parameter
@@ -44,20 +44,6 @@ LL - async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next(
 LL + async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
    |
 
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime.rs:17:69
-   |
-LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   | -----------------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   | |
-   | return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
-
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime.rs:9:63
-   |
-LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |      ----- has type `x`                                       ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs
index a48c5665d67..04ea3d831c9 100644
--- a/tests/ui/suggestions/missing-lt-for-hrtb.rs
+++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs
@@ -8,8 +8,6 @@ fn main() {
     let x = S(&|x| {
         println!("hi");
         x
-        //~^ ERROR lifetime may not live long enough
-        //~| ERROR lifetime may not live long enough
     });
     x.0(&X(&()));
 }
diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr
index e8c536ac47d..fa515644431 100644
--- a/tests/ui/suggestions/missing-lt-for-hrtb.stderr
+++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr
@@ -31,28 +31,6 @@ help: consider using one of the available lifetimes here
 LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>);
    |                                         +++++++++  +++++++++++
 
-error: lifetime may not live long enough
-  --> $DIR/missing-lt-for-hrtb.rs:10:9
-   |
-LL |     let x = S(&|x| {
-   |                 -- return type of closure is &'2 X<'_>
-   |                 |
-   |                 has type `&'1 X<'_>`
-LL |         println!("hi");
-LL |         x
-   |         ^ returning this value requires that `'1` must outlive `'2`
-
-error: lifetime may not live long enough
-  --> $DIR/missing-lt-for-hrtb.rs:10:9
-   |
-LL |     let x = S(&|x| {
-   |                 -- return type of closure is &X<'4>
-   |                 |
-   |                 has type `&X<'3>`
-LL |         println!("hi");
-LL |         x
-   |         ^ returning this value requires that `'3` must outlive `'4`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/target_modifiers/auxiliary/default_reg_struct_return.rs b/tests/ui/target_modifiers/auxiliary/default_reg_struct_return.rs
index 355e7c56e94..2bbdc839211 100644
--- a/tests/ui/target_modifiers/auxiliary/default_reg_struct_return.rs
+++ b/tests/ui/target_modifiers/auxiliary/default_reg_struct_return.rs
@@ -1,20 +1,7 @@
-//@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
+//@ no-prefer-dynamic
+//@ compile-flags: --target i686-unknown-linux-gnu
 //@ needs-llvm-components: x86
+
+#![feature(no_core)]
 #![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
-
-#[lang = "sized"]
-trait Sized {}
-#[lang = "copy"]
-trait Copy {}
-
-pub fn somefun() {}
-
-pub struct S;
diff --git a/tests/ui/target_modifiers/auxiliary/wrong_regparm.rs b/tests/ui/target_modifiers/auxiliary/wrong_regparm.rs
index 2e16f1ee747..267292faecd 100644
--- a/tests/ui/target_modifiers/auxiliary/wrong_regparm.rs
+++ b/tests/ui/target_modifiers/auxiliary/wrong_regparm.rs
@@ -1,20 +1,7 @@
-//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=2 -Cpanic=abort
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
+//@ no-prefer-dynamic
+//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=2
 //@ needs-llvm-components: x86
+
+#![feature(no_core)]
 #![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
-
-#[lang = "sized"]
-trait Sized {}
-#[lang = "copy"]
-trait Copy {}
-
-pub fn somefun() {}
-
-pub struct S;
diff --git a/tests/ui/target_modifiers/auxiliary/wrong_regparm_and_ret.rs b/tests/ui/target_modifiers/auxiliary/wrong_regparm_and_ret.rs
index 39c6be9d589..82ee3e71d16 100644
--- a/tests/ui/target_modifiers/auxiliary/wrong_regparm_and_ret.rs
+++ b/tests/ui/target_modifiers/auxiliary/wrong_regparm_and_ret.rs
@@ -1,20 +1,7 @@
-//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=2 -Zreg-struct-return=true -Cpanic=abort
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
+//@ no-prefer-dynamic
+//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=2 -Zreg-struct-return=true
 //@ needs-llvm-components: x86
+
+#![feature(no_core)]
 #![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
-
-#[lang = "sized"]
-trait Sized {}
-#[lang = "copy"]
-trait Copy {}
-
-pub fn somefun() {}
-
-pub struct S;
diff --git a/tests/ui/target_modifiers/defaults_check.error.stderr b/tests/ui/target_modifiers/defaults_check.error.stderr
index c545dd71069..4833fe90677 100644
--- a/tests/ui/target_modifiers/defaults_check.error.stderr
+++ b/tests/ui/target_modifiers/defaults_check.error.stderr
@@ -1,7 +1,7 @@
 error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `defaults_check`
-  --> $DIR/defaults_check.rs:20:1
+  --> $DIR/defaults_check.rs:15:1
    |
-LL | #![crate_type = "rlib"]
+LL | #![feature(no_core)]
    | ^
    |
    = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
diff --git a/tests/ui/target_modifiers/defaults_check.rs b/tests/ui/target_modifiers/defaults_check.rs
index b8f4848d3a4..de72acd32bc 100644
--- a/tests/ui/target_modifiers/defaults_check.rs
+++ b/tests/ui/target_modifiers/defaults_check.rs
@@ -1,27 +1,20 @@
 // Tests that default unspecified target modifier value in dependency crate is ok linked
 // with the same value, explicitly specified
-//@ aux-crate:default_reg_struct_return=default_reg_struct_return.rs
+
+//@ aux-build:default_reg_struct_return.rs
 //@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort
-//@ revisions:error ok ok_explicit
+//@ needs-llvm-components: x86
+
+//@ revisions: ok ok_explicit error
 //@[ok] compile-flags:
 //@[ok_explicit] compile-flags: -Zreg-struct-return=false
 //@[error] compile-flags: -Zreg-struct-return=true
+//@[ok] check-pass
+//@[ok_explicit] check-pass
 
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
-//@ needs-llvm-components: x86
-//@[ok] build-pass
-//@[ok_explicit] build-pass
-
-#![crate_type = "rlib"]
+#![feature(no_core)]
 //[error]~^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `defaults_check`
+#![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
 
-fn foo() {
-    default_reg_struct_return::somefun();
-}
+extern crate default_reg_struct_return;
diff --git a/tests/ui/target_modifiers/incompatible_regparm.error_generated.stderr b/tests/ui/target_modifiers/incompatible_regparm.error_generated.stderr
index 692fc7a4e3f..81015694d05 100644
--- a/tests/ui/target_modifiers/incompatible_regparm.error_generated.stderr
+++ b/tests/ui/target_modifiers/incompatible_regparm.error_generated.stderr
@@ -1,7 +1,7 @@
 error: mixing `-Zregparm` will cause an ABI mismatch in crate `incompatible_regparm`
-  --> $DIR/incompatible_regparm.rs:16:1
+  --> $DIR/incompatible_regparm.rs:11:1
    |
-LL | #![crate_type = "rlib"]
+LL | #![feature(no_core)]
    | ^
    |
    = help: the `-Zregparm` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
diff --git a/tests/ui/target_modifiers/incompatible_regparm.rs b/tests/ui/target_modifiers/incompatible_regparm.rs
index e866c5aa891..befe573b276 100644
--- a/tests/ui/target_modifiers/incompatible_regparm.rs
+++ b/tests/ui/target_modifiers/incompatible_regparm.rs
@@ -1,23 +1,16 @@
-//@ aux-crate:wrong_regparm=wrong_regparm.rs
-//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=1 -Cpanic=abort
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
+//@ aux-build:wrong_regparm.rs
+//@ compile-flags: --target i686-unknown-linux-gnu -Zregparm=1
 //@ needs-llvm-components: x86
-//@ revisions:error_generated allow_regparm_mismatch allow_no_value
 
+//@ revisions:allow_regparm_mismatch allow_no_value error_generated
 //@[allow_regparm_mismatch] compile-flags: -Cunsafe-allow-abi-mismatch=regparm
-//@[allow_regparm_mismatch] build-pass
 //@[allow_no_value] compile-flags: -Cunsafe-allow-abi-mismatch
+//@[error_generated] compile-flags:
+//@[allow_regparm_mismatch] check-pass
 
-#![crate_type = "rlib"]
+#![feature(no_core)]
 //[error_generated]~^ ERROR mixing `-Zregparm` will cause an ABI mismatch in crate `incompatible_regparm`
+#![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
 
-fn foo() {
-    wrong_regparm::somefun();
-}
+extern crate wrong_regparm;
diff --git a/tests/ui/target_modifiers/two_flags.rs b/tests/ui/target_modifiers/two_flags.rs
index ca17117a267..d5b5a923ca0 100644
--- a/tests/ui/target_modifiers/two_flags.rs
+++ b/tests/ui/target_modifiers/two_flags.rs
@@ -1,23 +1,15 @@
-//@ aux-crate:wrong_regparm_and_ret=wrong_regparm_and_ret.rs
-//@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort
-// Auxiliary build problems with aarch64-apple:
-// Shared library linking cc seems to convert "-m32" flag into -arch armv4t
-// Auxiliary build problems with i686-mingw: linker `cc` not found
-//@ only-x86
-//@ ignore-windows
-//@ ignore-apple
+//@ aux-build:wrong_regparm_and_ret.rs
+//@ compile-flags: --target i686-unknown-linux-gnu
 //@ needs-llvm-components: x86
-//@ revisions:two_allowed unknown_allowed
 
+//@ revisions:two_allowed unknown_allowed
 //@[two_allowed] compile-flags: -Cunsafe-allow-abi-mismatch=regparm,reg-struct-return
-//@[two_allowed] build-pass
 //@[unknown_allowed] compile-flags: -Cunsafe-allow-abi-mismatch=unknown_flag -Zregparm=2 -Zreg-struct-return=true
+//@[two_allowed] check-pass
 
-#![crate_type = "rlib"]
+#![feature(no_core)]
 //[unknown_allowed]~^ ERROR unknown target modifier `unknown_flag`, requested by `-Cunsafe-allow-abi-mismatch=unknown_flag`
+#![crate_type = "rlib"]
 #![no_core]
-#![feature(no_core, lang_items, repr_simd)]
 
-fn foo() {
-    wrong_regparm_and_ret::somefun();
-}
+extern crate wrong_regparm_and_ret;
diff --git a/tests/ui/target_modifiers/two_flags.unknown_allowed.stderr b/tests/ui/target_modifiers/two_flags.unknown_allowed.stderr
index c8040c6e389..248bde452f2 100644
--- a/tests/ui/target_modifiers/two_flags.unknown_allowed.stderr
+++ b/tests/ui/target_modifiers/two_flags.unknown_allowed.stderr
@@ -1,7 +1,7 @@
 error: unknown target modifier `unknown_flag`, requested by `-Cunsafe-allow-abi-mismatch=unknown_flag`
-  --> $DIR/two_flags.rs:16:1
+  --> $DIR/two_flags.rs:10:1
    |
-LL | #![crate_type = "rlib"]
+LL | #![feature(no_core)]
    | ^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
index 76e015a7238..4609e02716f 100644
--- a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
+++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
@@ -11,6 +11,7 @@ LL | const TEST: Fn = some_fn;
    |             ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
+   = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
   --> $DIR/ice-unsized-tuple-const-issue-121443.rs:11:14
diff --git a/tests/ui/traits/next-solver/unsize-good.rs b/tests/ui/traits/next-solver/unsize-good.rs
index 4456e4f2188..f3d8b08e693 100644
--- a/tests/ui/traits/next-solver/unsize-good.rs
+++ b/tests/ui/traits/next-solver/unsize-good.rs
@@ -1,8 +1,6 @@
 //@ compile-flags: -Znext-solver
 //@ check-pass
 
-#![feature(unsized_tuple_coercion)]
-
 trait Foo {}
 
 impl Foo for i32 {}
@@ -15,10 +13,6 @@ fn main() {
     let y = [1, 2, 3];
     let _: &[i32] = &y;
 
-    // Tuple unsizing
-    let hi = (1i32,);
-    let _: &(dyn Foo,) = &hi;
-
     // Dropping auto traits
     let a: &(dyn Foo + Send) = &1;
     let _: &dyn Foo = a;
diff --git a/tests/ui/traits/on_unimplemented_long_types.rs b/tests/ui/traits/on_unimplemented_long_types.rs
index c652b71e51a..d6c3e8ef75f 100644
--- a/tests/ui/traits/on_unimplemented_long_types.rs
+++ b/tests/ui/traits/on_unimplemented_long_types.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: --diagnostic-width=60 -Z write-long-types-to-disk=yes
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 
 pub fn foo() -> impl std::fmt::Display {
     //~^ ERROR doesn't implement `std::fmt::Display`
diff --git a/tests/ui/traits/on_unimplemented_long_types.stderr b/tests/ui/traits/on_unimplemented_long_types.stderr
index 2705d7c501e..1628466e081 100644
--- a/tests/ui/traits/on_unimplemented_long_types.stderr
+++ b/tests/ui/traits/on_unimplemented_long_types.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Option<Option<Option<...>>>` doesn't implement `std::fmt::Display`
-  --> $DIR/on_unimplemented_long_types.rs:5:17
+  --> $DIR/on_unimplemented_long_types.rs:3:17
    |
 LL |   pub fn foo() -> impl std::fmt::Display {
    |                   ^^^^^^^^^^^^^^^^^^^^^^ `Option<Option<Option<...>>>` cannot be formatted with the default formatter
@@ -15,7 +15,7 @@ LL | |     )))))))))))
    |
    = help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/on_unimplemented_long_types.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
index 2383008d042..43df49adc42 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -2,10 +2,12 @@
 #![allow(dead_code)]
 
 type Bug<T, U> = impl Fn(T) -> U + Copy;
+//~^ ERROR cycle detected
 
 const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-//~^ ERROR cycle detected
-//~| ERROR: non-defining opaque type use
+//~^ ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature
+//~| ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature
+//~| ERROR non-defining opaque type use in defining scope
 
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
     |x| x.into()
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
index ac580866704..678b0c84f78 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -1,5 +1,5 @@
 error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/issue-53092-2.rs:6:18
+  --> $DIR/issue-53092-2.rs:7:18
    |
 LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
    |                  ^^^^^^^^^^^ argument `u8` is not a generic parameter
@@ -10,33 +10,59 @@ note: for this opaque type
 LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0391]: cycle detected when type-checking `CONST_BUG`
-  --> $DIR/issue-53092-2.rs:6:1
+error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of opaque `Bug::{opaque#0}`...
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:7:1
    |
 LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
    = note: ...which requires computing layout of `Bug<u8, ()>`...
    = note: ...which requires normalizing `Bug<u8, ()>`...
-note: ...which requires computing type of `Bug::{opaque#0}`...
+   = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
+note: cycle used when checking that `Bug::{opaque#0}` is well-formed
   --> $DIR/issue-53092-2.rs:4:18
    |
 LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires computing type of opaque `Bug::{opaque#0}`...
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: item does not constrain `Bug::{opaque#0}`, but has it in its signature
+  --> $DIR/issue-53092-2.rs:7:7
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   |       ^^^^^^^^^
+   |
+   = note: consider moving the opaque type's declaration and defining uses into a separate module
+note: this opaque type is in the signature
   --> $DIR/issue-53092-2.rs:4:18
    |
 LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires type-checking `CONST_BUG`, completing the cycle
-note: cycle used when checking that `CONST_BUG` is well-formed
-  --> $DIR/issue-53092-2.rs:6:1
+
+error: item does not constrain `Bug::{opaque#0}`, but has it in its signature
+  --> $DIR/issue-53092-2.rs:7:61
    |
 LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+   |                                                             ^^^^^^^
+   |
+   = note: consider moving the opaque type's declaration and defining uses into a separate module
+note: this opaque type is in the signature
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0391, E0792.
 For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/type_length_limit.rs b/tests/ui/type_length_limit.rs
index b629455aced..87f5ffd76d7 100644
--- a/tests/ui/type_length_limit.rs
+++ b/tests/ui/type_length_limit.rs
@@ -2,9 +2,6 @@
 //@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
 //~^^ ERROR reached the type-length limit
 
-// The regex below normalizes the long type file name to make it suitable for compare-modes.
-//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
-
 // Test that the type length limit can be changed.
 // The exact type depends on optimizations, so disable them.
 
diff --git a/tests/ui/type_length_limit.stderr b/tests/ui/type_length_limit.stderr
index d913b661c6f..198d133c08c 100644
--- a/tests/ui/type_length_limit.stderr
+++ b/tests/ui/type_length_limit.stderr
@@ -1,11 +1,11 @@
 error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
-  --> $DIR/type_length_limit.rs:35:5
+  --> $DIR/type_length_limit.rs:32:5
    |
 LL |     drop::<Option<A>>(None);
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
-   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit.long-type.txt'
 
 error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
    |
diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs
new file mode 100644
index 00000000000..dda362a595e
--- /dev/null
+++ b/tests/ui/unpretty/deprecated-attr.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Zunpretty=hir
+//@ check-pass
+
+#[deprecated]
+pub struct PlainDeprecated;
+
+#[deprecated = "here's why this is deprecated"]
+pub struct DirectNote;
+
+#[deprecated(note = "here's why this is deprecated")]
+pub struct ExplicitNote;
+
+#[deprecated(since = "1.2.3", note = "here's why this is deprecated")]
+pub struct SinceAndNote;
+
+#[deprecated(note = "here's why this is deprecated", since = "1.2.3")]
+pub struct FlippedOrder;
diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout
new file mode 100644
index 00000000000..60dbac1072b
--- /dev/null
+++ b/tests/ui/unpretty/deprecated-attr.stdout
@@ -0,0 +1,21 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ compile-flags: -Zunpretty=hir
+//@ check-pass
+
+#[deprecated]
+struct PlainDeprecated;
+
+#[deprecated = "here's why this is deprecated"]
+struct DirectNote;
+
+#[deprecated = "here's why this is deprecated"]
+struct ExplicitNote;
+
+#[deprecated(since = "1.2.3", note = "here's why this is deprecated"]
+struct SinceAndNote;
+
+#[deprecated(since = "1.2.3", note = "here's why this is deprecated"]
+struct FlippedOrder;
diff --git a/tests/ui/unpretty/diagnostic-attr.rs b/tests/ui/unpretty/diagnostic-attr.rs
new file mode 100644
index 00000000000..27f5b693e69
--- /dev/null
+++ b/tests/ui/unpretty/diagnostic-attr.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Zunpretty=hir
+//@ check-pass
+
+#[diagnostic::on_unimplemented(
+    message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`",
+    label = "My Label",
+    note = "Note 1",
+    note = "Note 2"
+)]
+pub trait ImportantTrait<A> {}
+
+#[diagnostic::do_not_recommend]
+impl<T> ImportantTrait<T> for T where T: Clone {}
diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout
new file mode 100644
index 00000000000..e8696d04d38
--- /dev/null
+++ b/tests/ui/unpretty/diagnostic-attr.stdout
@@ -0,0 +1,16 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ compile-flags: -Zunpretty=hir
+//@ check-pass
+
+#[diagnostic::on_unimplemented(message =
+"My Message for `ImportantTrait<{A}>` implemented for `{Self}`", label =
+"My Label", note = "Note 1", note = "Note 2")]
+trait ImportantTrait<A> { }
+
+#[diagnostic::do_not_recommend]
+impl <T> ImportantTrait<T> for T where T: Clone
+    {#![diagnostic::do_not_recommend]
+}
diff --git a/tests/ui/unsafe-binders/type-mismatch.rs b/tests/ui/unsafe-binders/type-mismatch.rs
new file mode 100644
index 00000000000..9ac4e817c28
--- /dev/null
+++ b/tests/ui/unsafe-binders/type-mismatch.rs
@@ -0,0 +1,9 @@
+#![feature(unsafe_binders)]
+//~^ WARN the feature `unsafe_binders` is incomplete
+
+fn main() {
+    let x: unsafe<> i32 = 0;
+    //~^ ERROR mismatched types
+    let x: unsafe<'a> &'a i32 = &0;
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/unsafe-binders/type-mismatch.stderr b/tests/ui/unsafe-binders/type-mismatch.stderr
new file mode 100644
index 00000000000..e694b5d464d
--- /dev/null
+++ b/tests/ui/unsafe-binders/type-mismatch.stderr
@@ -0,0 +1,34 @@
+warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/type-mismatch.rs:1:12
+   |
+LL | #![feature(unsafe_binders)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:5:27
+   |
+LL |     let x: unsafe<> i32 = 0;
+   |            ------------   ^ expected `unsafe<> i32`, found integer
+   |            |
+   |            expected due to this
+   |
+   = note: expected unsafe binder `unsafe<> i32`
+                       found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:7:33
+   |
+LL |     let x: unsafe<'a> &'a i32 = &0;
+   |            ------------------   ^^ expected `unsafe<'a> &i32`, found `&{integer}`
+   |            |
+   |            expected due to this
+   |
+   = note: expected unsafe binder `unsafe<'a> &'a i32`
+                  found reference `&{integer}`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/unsized-locals/rust-call.rs b/tests/ui/unsized-locals/rust-call.rs
deleted file mode 100644
index ff4075aa4c0..00000000000
--- a/tests/ui/unsized-locals/rust-call.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(unsized_tuple_coercion)]
-#![feature(unboxed_closures)]
-#![feature(unsized_fn_params)]
-
-fn bad() -> extern "rust-call" fn(([u8],)) { todo!() }
-
-fn main() {
-    let f = bad();
-    let slice: Box<([u8],)> = Box::new(([1; 8],));
-    f(*slice);
-    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
-}
diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr
deleted file mode 100644
index 9eb0f3dabcc..00000000000
--- a/tests/ui/unsized-locals/rust-call.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/rust-call.rs:10:7
-   |
-LL |     f(*slice);
-   |       ^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`
-   = note: required because it appears within the type `([u8],)`
-   = note: argument required to be sized due to `extern "rust-call"` ABI
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsized-locals/unsized-exprs-rpass.rs b/tests/ui/unsized-locals/unsized-exprs-rpass.rs
index a5aada20d3e..861583efc40 100644
--- a/tests/ui/unsized-locals/unsized-exprs-rpass.rs
+++ b/tests/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(incomplete_features, unused_braces, unused_parens)]
-#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 struct A<X: ?Sized>(#[allow(dead_code)] X);
 
@@ -8,9 +8,6 @@ fn udrop<T: ?Sized>(_x: T) {}
 fn foo() -> Box<[u8]> {
     Box::new(*b"foo")
 }
-fn tfoo() -> Box<(i32, [u8])> {
-    Box::new((42, *b"foo"))
-}
 fn afoo() -> Box<A<[u8]>> {
     Box::new(A(*b"foo"))
 }
@@ -27,7 +24,6 @@ fn main() {
     udrop::<[u8]>(if true { *foo() } else { *foo() });
     udrop::<[u8]>({ *foo() });
     udrop::<[u8]>((*foo()));
-    udrop::<[u8]>((*tfoo()).1);
     *afoo() + 42;
     udrop as fn([u8]);
 }
diff --git a/tests/ui/unsized-locals/unsized-exprs.rs b/tests/ui/unsized-locals/unsized-exprs.rs
index 1729b9ffa86..8fe5dcba8a9 100644
--- a/tests/ui/unsized-locals/unsized-exprs.rs
+++ b/tests/ui/unsized-locals/unsized-exprs.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_fn_params)]
+#![feature(unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
@@ -6,9 +6,6 @@ fn udrop<T: ?Sized>(_x: T) {}
 fn foo() -> Box<[u8]> {
     Box::new(*b"foo")
 }
-fn tfoo() -> Box<(i32, [u8])> {
-    Box::new((42, *b"foo"))
-}
 fn afoo() -> Box<A<[u8]>> {
     Box::new(A(*b"foo"))
 }
@@ -19,8 +16,6 @@ impl std::ops::Add<i32> for A<[u8]> {
 }
 
 fn main() {
-    udrop::<(i32, [u8])>((42, *foo()));
-    //~^ERROR E0277
     udrop::<A<[u8]>>(A { 0: *foo() });
     //~^ERROR E0277
     udrop::<A<[u8]>>(A(*foo()));
diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr
index 8a2ecf0f6c3..1b61254870f 100644
--- a/tests/ui/unsized-locals/unsized-exprs.stderr
+++ b/tests/ui/unsized-locals/unsized-exprs.stderr
@@ -1,15 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:22:26
-   |
-LL |     udrop::<(i32, [u8])>((42, *foo()));
-   |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`
-   = note: required because it appears within the type `({integer}, [u8])`
-   = note: tuples must have a statically known size to be initialized
-
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:24:22
+  --> $DIR/unsized-exprs.rs:19:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -23,7 +13,7 @@ LL | struct A<X: ?Sized>(X);
    = note: structs must have a statically known size to be initialized
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:26:22
+  --> $DIR/unsized-exprs.rs:21:22
    |
 LL |     udrop::<A<[u8]>>(A(*foo()));
    |                      ^^^^^^^^^ doesn't have a size known at compile-time
@@ -36,6 +26,6 @@ LL | struct A<X: ?Sized>(X);
    |        ^
    = note: the return type of a function must have a statically known size
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsized-locals/unsized-exprs2.rs b/tests/ui/unsized-locals/unsized-exprs2.rs
index 127d8717e58..7706c8b8b8f 100644
--- a/tests/ui/unsized-locals/unsized-exprs2.rs
+++ b/tests/ui/unsized-locals/unsized-exprs2.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_fn_params)]
+#![feature(unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
@@ -6,9 +6,6 @@ fn udrop<T: ?Sized>(_x: T) {}
 fn foo() -> Box<[u8]> {
     Box::new(*b"foo")
 }
-fn tfoo() -> Box<(i32, [u8])> {
-    Box::new((42, *b"foo"))
-}
 fn afoo() -> Box<A<[u8]>> {
     Box::new(A(*b"foo"))
 }
diff --git a/tests/ui/unsized-locals/unsized-exprs2.stderr b/tests/ui/unsized-locals/unsized-exprs2.stderr
index 47b6d72acc7..79f0d93d421 100644
--- a/tests/ui/unsized-locals/unsized-exprs2.stderr
+++ b/tests/ui/unsized-locals/unsized-exprs2.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[u8]`, a non-copy slice
-  --> $DIR/unsized-exprs2.rs:22:5
+  --> $DIR/unsized-exprs2.rs:19:5
    |
 LL |     udrop::<[u8]>(foo()[..]);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unsized/unsized-tuple-impls.rs b/tests/ui/unsized/unsized-tuple-impls.rs
deleted file mode 100644
index a76e2df5750..00000000000
--- a/tests/ui/unsized/unsized-tuple-impls.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ run-pass
-
-#![feature(unsized_tuple_coercion)]
-
-use std::collections::HashSet;
-
-fn main() {
-    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])]");
-
-    let mut h = HashSet::new();
-    h.insert(x);
-    h.insert(y);
-    assert!(h.contains(x));
-    assert!(h.contains(y));
-}
diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr
index 83b56bb6b19..66c4f214415 100644
--- a/tests/ui/wf/wf-normalization-sized.next.stderr
+++ b/tests/ui/wf/wf-normalization-sized.next.stderr
@@ -7,16 +7,6 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
    = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
    = note: slice and array elements must have `Sized` type
 
-error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
-  --> $DIR/wf-normalization-sized.rs:19:11
-   |
-LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
-   |           ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
-   = note: slice and array elements must have `Sized` type
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/wf-normalization-sized.rs:22:11
    |
@@ -27,6 +17,16 @@ LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
 note: required by an implicit `Sized` bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
+error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
+  --> $DIR/wf-normalization-sized.rs:19:11
+   |
+LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
+   |           ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
+   = note: slice and array elements must have `Sized` type
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/wf-normalization-sized.rs:22:11
    |
diff --git a/tests/ui/where-clauses/cfg_attribute.a.stderr b/tests/ui/where-clauses/cfg_attribute.a.stderr
new file mode 100644
index 00000000000..0ede890eb44
--- /dev/null
+++ b/tests/ui/where-clauses/cfg_attribute.a.stderr
@@ -0,0 +1,288 @@
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:32:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:43:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:54:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:66:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:76:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:87:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:100:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:114:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:129:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:144:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:155:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:165:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:178:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:32:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:35:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:66:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:69:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:100:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:103:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:114:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:117:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:129:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:132:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:144:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:147:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:155:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:158:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:178:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:181:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:43:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:46:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:54:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:57:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:76:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:79:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:87:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:90:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:165:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:168:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: aborting due to 39 previous errors
+
diff --git a/tests/ui/where-clauses/cfg_attribute.b.stderr b/tests/ui/where-clauses/cfg_attribute.b.stderr
new file mode 100644
index 00000000000..0ede890eb44
--- /dev/null
+++ b/tests/ui/where-clauses/cfg_attribute.b.stderr
@@ -0,0 +1,288 @@
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:32:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:43:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:54:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:66:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:76:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:87:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:100:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:114:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:129:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:144:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:155:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:165:11
+   |
+LL |         #[derive(Clone)] ():,
+   |           ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/cfg_attribute.rs:178:7
+   |
+LL |     #[derive(Clone)] ():,
+   |       ^^^^^^ not a non-macro attribute
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:32:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:35:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:66:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:69:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:100:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:103:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:114:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:117:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:129:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:132:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:144:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:147:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:155:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:158:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:178:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:181:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:43:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:46:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:54:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:57:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:76:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:79:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:87:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:90:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:165:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:168:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: aborting due to 39 previous errors
+
diff --git a/tests/ui/where-clauses/cfg_attribute.rs b/tests/ui/where-clauses/cfg_attribute.rs
new file mode 100644
index 00000000000..8cbca0bee75
--- /dev/null
+++ b/tests/ui/where-clauses/cfg_attribute.rs
@@ -0,0 +1,183 @@
+//@ revisions: a b
+
+#![crate_type = "lib"]
+#![feature(alloc_error_handler)]
+#![feature(cfg_accessible)]
+#![feature(cfg_eval)]
+#![feature(custom_test_frameworks)]
+#![feature(derive_const)]
+#![feature(where_clause_attrs)]
+#![allow(soft_unstable)]
+
+use std::marker::PhantomData;
+
+#[cfg(a)]
+trait TraitA {}
+
+#[cfg(b)]
+trait TraitB {}
+
+#[cfg_attr(a, cfg(a))]
+trait TraitAA {}
+
+#[cfg_attr(b, cfg(b))]
+trait TraitBB {}
+
+trait A<T>
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+    type B<U>
+    where
+        #[cfg(a)] U: TraitA,
+        #[cfg(b)] U: TraitB,
+        #[cfg_attr(a, cfg(a))] U: TraitAA,
+        #[cfg_attr(b, cfg(b))] U: TraitBB,
+        #[derive(Clone)] ():,
+        //~^ ERROR most attributes are not supported in `where` clauses
+        //~| ERROR expected non-macro attribute, found attribute macro `derive`
+        #[rustfmt::skip] ():; //~ ERROR most attributes are not supported in `where` clauses
+
+    fn foo<U>(&self)
+    where
+        #[cfg(a)] U: TraitA,
+        #[cfg(b)] U: TraitB,
+        #[cfg_attr(a, cfg(a))] U: TraitAA,
+        #[cfg_attr(b, cfg(b))] U: TraitBB,
+        #[derive(Clone)] ():,
+        //~^ ERROR most attributes are not supported in `where` clauses
+        //~| ERROR expected non-macro attribute, found attribute macro `derive`
+        #[rustfmt::skip] ():; //~ ERROR most attributes are not supported in `where` clauses
+}
+
+impl<T> A<T> for T
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+    type B<U> = () where
+        #[cfg(a)] U: TraitA,
+        #[cfg(b)] U: TraitB,
+        #[cfg_attr(a, cfg(a))] U: TraitAA,
+        #[cfg_attr(b, cfg(b))] U: TraitBB,
+        #[derive(Clone)] ():,
+        //~^ ERROR most attributes are not supported in `where` clauses
+        //~| ERROR expected non-macro attribute, found attribute macro `derive`
+        #[rustfmt::skip] ():; //~ ERROR most attributes are not supported in `where` clauses
+
+    fn foo<U>(&self)
+    where
+        #[cfg(a)] U: TraitA,
+        #[cfg(b)] U: TraitB,
+        #[cfg_attr(a, cfg(a))] U: TraitAA,
+        #[cfg_attr(b, cfg(b))] U: TraitBB,
+        #[derive(Clone)] ():,
+        //~^ ERROR most attributes are not supported in `where` clauses
+        //~| ERROR expected non-macro attribute, found attribute macro `derive`
+        #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+    {}
+}
+
+struct C<T>
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+    _t: PhantomData<T>,
+}
+
+union D<T>
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+
+    _t: PhantomData<T>,
+}
+
+enum E<T>
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+    E(PhantomData<T>),
+}
+
+#[allow(type_alias_bounds)]
+type F<T>
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+= T;
+
+impl<T> C<T> where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+    fn new<U>() where
+        #[cfg(a)] U: TraitA,
+        #[cfg(b)] U: TraitB,
+        #[cfg_attr(a, cfg(a))] U: TraitAA,
+        #[cfg_attr(b, cfg(b))] U: TraitBB,
+        #[derive(Clone)] ():,
+        //~^ ERROR most attributes are not supported in `where` clauses
+        //~| ERROR expected non-macro attribute, found attribute macro `derive`
+        #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+    {}
+}
+
+fn foo<T>()
+where
+    #[cfg(a)] T: TraitA,
+    #[cfg(b)] T: TraitB,
+    #[cfg_attr(a, cfg(a))] T: TraitAA,
+    #[cfg_attr(b, cfg(b))] T: TraitBB,
+    #[derive(Clone)] ():,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] ():, //~ ERROR most attributes are not supported in `where` clauses
+{
+}
diff --git a/tests/ui/where-clauses/unsupported_attribute.rs b/tests/ui/where-clauses/unsupported_attribute.rs
new file mode 100644
index 00000000000..33128b383b9
--- /dev/null
+++ b/tests/ui/where-clauses/unsupported_attribute.rs
@@ -0,0 +1,36 @@
+#![crate_type = "lib"]
+#![feature(alloc_error_handler)]
+#![feature(cfg_accessible)]
+#![feature(cfg_eval)]
+#![feature(custom_test_frameworks)]
+#![feature(derive_const)]
+#![feature(where_clause_attrs)]
+#![allow(soft_unstable)]
+
+trait Trait {}
+
+fn foo<'a, T>()
+where
+    #[doc = "doc"] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[doc = "doc"] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[ignore] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[ignore] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[should_panic] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[should_panic] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[macro_use] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[macro_use] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[allow(unused)] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[allow(unused)] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[deprecated] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[deprecated] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[automatically_derived] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[automatically_derived] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[derive(Clone)] T: Trait,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[derive(Clone)] 'a: 'static,
+    //~^ ERROR most attributes are not supported in `where` clauses
+    //~| ERROR expected non-macro attribute, found attribute macro `derive`
+    #[rustfmt::skip] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
+    #[rustfmt::skip] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+{}
diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr
new file mode 100644
index 00000000000..ecb28039f88
--- /dev/null
+++ b/tests/ui/where-clauses/unsupported_attribute.stderr
@@ -0,0 +1,158 @@
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/unsupported_attribute.rs:28:7
+   |
+LL |     #[derive(Clone)] T: Trait,
+   |       ^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `derive`
+  --> $DIR/unsupported_attribute.rs:31:7
+   |
+LL |     #[derive(Clone)] 'a: 'static,
+   |       ^^^^^^ not a non-macro attribute
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:14:5
+   |
+LL |     #[doc = "doc"] T: Trait,
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:15:5
+   |
+LL |     #[doc = "doc"] 'a: 'static,
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:16:5
+   |
+LL |     #[ignore] T: Trait,
+   |     ^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:17:5
+   |
+LL |     #[ignore] 'a: 'static,
+   |     ^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:18:5
+   |
+LL |     #[should_panic] T: Trait,
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:19:5
+   |
+LL |     #[should_panic] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:20:5
+   |
+LL |     #[macro_use] T: Trait,
+   |     ^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:21:5
+   |
+LL |     #[macro_use] 'a: 'static,
+   |     ^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:22:5
+   |
+LL |     #[allow(unused)] T: Trait,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:23:5
+   |
+LL |     #[allow(unused)] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:24:5
+   |
+LL |     #[deprecated] T: Trait,
+   |     ^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:25:5
+   |
+LL |     #[deprecated] 'a: 'static,
+   |     ^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:26:5
+   |
+LL |     #[automatically_derived] T: Trait,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:27:5
+   |
+LL |     #[automatically_derived] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:28:5
+   |
+LL |     #[derive(Clone)] T: Trait,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:31:5
+   |
+LL |     #[derive(Clone)] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:34:5
+   |
+LL |     #[rustfmt::skip] T: Trait,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:35:5
+   |
+LL |     #[rustfmt::skip] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: aborting due to 20 previous errors
+
diff --git a/triagebot.toml b/triagebot.toml
index 7702d4133ac..ff789e6e362 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -207,7 +207,7 @@ trigger_files = [
     "tests/rustdoc",
     "tests/rustdoc-ui",
     "tests/rustdoc-gui",
-    "tests/rustdoc-js",
+    "tests/rustdoc-js/",
     "tests/rustdoc-js-std",
     "tests/rustdoc-json",
 
@@ -775,7 +775,7 @@ cc = ["@fmease"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]
 
-[mentions."compiler/rustc_mir_build/src/build/matches"]
+[mentions."compiler/rustc_mir_build/src/builder/matches"]
 message = "Some changes occurred in match lowering"
 cc = ["@Nadrieril"]
 
@@ -838,13 +838,7 @@ message = "Some changes occurred in GUI tests."
 cc = ["@GuillaumeGomez"]
 
 [mentions."tests/run-make/"]
-message = """
-This PR modifies `tests/run-make/`. If this PR is trying to port a Makefile
-run-make test to use rmake.rs, please update the
-[run-make port tracking issue](https://github.com/rust-lang/rust/issues/121876)
-so we can track our progress. You can either modify the tracking issue
-directly, or you can comment on the tracking issue and link this PR.
-"""
+message = "This PR modifies `run-make` tests."
 cc = ["@jieyouxu"]
 
 [mentions."src/rustdoc-json-types"]
@@ -1035,7 +1029,7 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 message = "Some changes occurred in coverage instrumentation."
 cc = ["@Zalathar"]
 
-[mentions."compiler/rustc_mir_build/src/build/coverageinfo.rs"]
+[mentions."compiler/rustc_mir_build/src/builder/coverageinfo.rs"]
 message = "Some changes occurred in coverage instrumentation."
 cc = ["@Zalathar"]
 
@@ -1264,7 +1258,7 @@ project-exploit-mitigations = [
 "/compiler/rustc_middle/src/ty" =                        ["compiler", "types"]
 "/compiler/rustc_const_eval/src/interpret" =             ["compiler", "mir"]
 "/compiler/rustc_const_eval/src/transform" =             ["compiler", "mir-opt"]
-"/compiler/rustc_mir_build/src/build" =                  ["compiler", "mir"]
+"/compiler/rustc_mir_build/src/builder" =                ["compiler", "mir"]
 "/compiler/rustc_mir_transform" =                        ["compiler", "mir", "mir-opt"]
 "/compiler/rustc_smir" =                                 ["project-stable-mir"]
 "/compiler/rustc_parse" =                                ["compiler", "parser"]
@@ -1307,7 +1301,7 @@ project-exploit-mitigations = [
 "/tests/rustdoc" =                                       ["rustdoc"]
 "/tests/rustdoc-gui" =                                   ["rustdoc"]
 "/tests/rustdoc-js-std" =                                ["rustdoc"]
-"/tests/rustdoc-js" =                                    ["rustdoc"]
+"/tests/rustdoc-js/" =                                   ["rustdoc"]
 "/tests/rustdoc-json" =                                  ["@aDotInTheVoid"]
 "/tests/rustdoc-ui" =                                    ["rustdoc"]
 "/tests/ui" =                                            ["compiler"]
diff --git a/x b/x
index e656d37c1e4..551cfe6efbf 100755
--- a/x
+++ b/x
@@ -25,7 +25,13 @@ xpy=$(dirname "$(realpath "$0")")/x.py
 
 # On Windows, `py -3` sometimes works. We need to try it first because `python3`
 # sometimes tries to launch the app store on Windows.
-for SEARCH_PYTHON in py python3 python python2; do
+# On MacOS, `py` tries to install "Developer command line tools". Try `python3` first.
+# NOTE: running `bash -c ./x` from Windows doesn't set OSTYPE.
+case ${OSTYPE:-} in
+    cygwin*|msys*) SEARCH="py python3 python python2";;
+    *) SEARCH="python3 python py python2";;
+esac
+for SEARCH_PYTHON in $SEARCH; do
     if python=$(command -v $SEARCH_PYTHON) && [ -x "$python" ]; then
         if [ $SEARCH_PYTHON = py ]; then
             extra_arg="-3"