about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2025-08-10 01:45:38 +0000
committerGitHub <noreply@github.com>2025-08-10 01:45:38 +0000
commit85c8d7089035d60c63a0594b07ff48981399f2ed (patch)
treef126cf7695965577ab96b9c27e5a9c5c491f8dd2 /src
parentee1b237215ee90df2c0102457fa2d0e9c2df8753 (diff)
parent6e83b592cddec5ab61f1e4307134fd8f4069351e (diff)
Merge pull request #4518 from rust-lang/rustup-2025-08-09
Automatic Rustup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs85
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs241
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs48
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs10
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/perf.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/run.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs292
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs435
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs19
-rw-r--r--src/bootstrap/src/core/builder/mod.rs40
-rw-r--r--src/bootstrap/src/core/builder/tests.rs403
-rw-r--r--src/bootstrap/src/core/config/config.rs1327
-rw-r--r--src/bootstrap/src/core/config/toml/dist.rs33
-rw-r--r--src/bootstrap/src/core/config/toml/gcc.rs21
-rw-r--r--src/bootstrap/src/core/config/toml/install.rs22
-rw-r--r--src/bootstrap/src/core/config/toml/llvm.rs129
-rw-r--r--src/bootstrap/src/core/config/toml/mod.rs2
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs263
-rw-r--r--src/bootstrap/src/core/config/toml/target.rs75
-rw-r--r--src/bootstrap/src/core/sanity.rs1
-rw-r--r--src/bootstrap/src/lib.rs22
-rw-r--r--src/bootstrap/src/utils/exec.rs12
-rw-r--r--src/bootstrap/src/utils/helpers.rs23
-rwxr-xr-xsrc/ci/docker/scripts/build-clang.sh6
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc-dev-guide/rust-version2
-rw-r--r--src/doc/rustc-dev-guide/src/offload/installation.md2
-rw-r--r--src/doc/rustc-dev-guide/src/overview.md4
-rw-r--r--src/doc/rustc-dev-guide/src/stability.md3
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md23
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios-macabi.md11
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md14
-rw-r--r--src/doc/rustc/src/platform-support/armv7a-vex-v5.md83
-rw-r--r--src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md40
-rw-r--r--src/doc/unstable-book/src/compiler-flags/coverage-options.md5
-rw-r--r--src/librustdoc/clean/types.rs20
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs7
-rw-r--r--src/librustdoc/scrape_examples.rs7
m---------src/llvm-project0
-rw-r--r--src/stage0980
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.yml21
-rwxr-xr-xsrc/tools/clippy/.github/driver.sh6
-rw-r--r--src/tools/clippy/CHANGELOG.md101
-rw-r--r--src/tools/clippy/CONTRIBUTING.md44
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md2
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs2
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/inline_always.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cloned_ref_to_slice_refs.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/coerce_container_to_any.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_if.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/broken_link.rs76
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_with_brackets.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/four_forward_slashes.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/if_not_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/incompatible_msrv.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/infallible_try_from.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs246
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/ip_constant.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs78
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_block.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs109
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/mod.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/derive_deserialize_allowing_unknown.rs5
-rw-r--r--src/tools/clippy/clippy_test_deps/Cargo.lock7
-rw-r--r--src/tools/clippy/clippy_test_deps/Cargo.toml1
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/README.md2
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs116
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs127
-rw-r--r--src/tools/clippy/clippy_utils/src/sym.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/mod.rs7
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/src/input.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/json.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/output.rs2
-rw-r--r--src/tools/clippy/rust-toolchain.toml2
-rw-r--r--src/tools/clippy/tests/compile-test.rs11
-rw-r--r--src/tools/clippy/tests/symbols-used.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr2
-rw-r--r--src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr10
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed11
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs11
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr6
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer_unfixable.rs17
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.fixed22
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.rs24
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.stderr11
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed18
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs19
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr20
-rw-r--r--src/tools/clippy/tests/ui/deprecated.rs1
-rw-r--r--src/tools/clippy/tests/ui/deprecated.stderr18
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/duplicated_attributes.rs2
-rw-r--r--src/tools/clippy/tests/ui/duplicated_attributes.stderr23
-rw-r--r--src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed14
-rw-r--r--src/tools/clippy/tests/ui/empty_structs_with_brackets.rs14
-rw-r--r--src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr10
-rw-r--r--src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.rs6
-rw-r--r--src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.stderr14
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.fixed6
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.rs6
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.stderr14
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed12
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs12
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr11
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.rs1
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.stderr38
-rw-r--r--src/tools/clippy/tests/ui/infallible_try_from.stderr4
-rw-r--r--src/tools/clippy/tests/ui/ip_constant.fixed14
-rw-r--r--src/tools/clippy/tests/ui/ip_constant.rs14
-rw-r--r--src/tools/clippy/tests/ui/ip_constant.stderr80
-rw-r--r--src/tools/clippy/tests/ui/iter_on_single_items.fixed24
-rw-r--r--src/tools/clippy/tests/ui/iter_on_single_items.rs24
-rw-r--r--src/tools/clippy/tests/ui/let_unit.fixed11
-rw-r--r--src/tools/clippy/tests/ui/let_unit.rs10
-rw-r--r--src/tools/clippy/tests/ui/let_unit.stderr16
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.fixed12
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.rs12
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.stderr50
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_strip.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_identity.fixed64
-rw-r--r--src/tools/clippy/tests/ui/map_identity.rs64
-rw-r--r--src/tools/clippy/tests/ui/map_identity.stderr38
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed62
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs76
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.stderr116
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.rs49
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.stderr80
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.stderr32
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.rs18
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.stderr18
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed12
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs16
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr19
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.rs15
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr17
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed7
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.rs7
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr8
-rw-r--r--src/tools/clippy/tests/ui/string_to_string.rs21
-rw-r--r--src/tools/clippy/tests/ui/string_to_string.stderr28
-rw-r--r--src/tools/clippy/tests/ui/string_to_string_in_map.fixed20
-rw-r--r--src/tools/clippy/tests/ui/string_to_string_in_map.rs20
-rw-r--r--src/tools/clippy/tests/ui/string_to_string_in_map.stderr38
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.rs10
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.stderr6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs3
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr46
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.fixed20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.rs20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.stderr30
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.stderr12
-rw-r--r--src/tools/clippy/triagebot.toml1
-rw-r--r--src/tools/clippy/util/gh-pages/index_template.html37
-rw-r--r--src/tools/clippy/util/gh-pages/script.js13
-rw-r--r--src/tools/clippy/util/gh-pages/style.css369
-rw-r--r--src/tools/compiletest/src/directives/tests.rs7
-rw-r--r--src/tools/compiletest/src/runtest.rs7
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs19
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/operator.rs10
-rw-r--r--src/tools/miri/src/shims/extern_static.rs2
-rw-r--r--src/tools/miri/src/shims/unix/android/foreign_items.rs11
-rw-r--r--src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr8
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr8
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/abort_unwind.stderr8
-rw-r--r--src/tools/miri/tests/fail/panic/bad_unwind.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr10
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.stderr6
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.stderr6
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.stderr6
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.stderr6
-rw-r--r--src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr2
-rw-r--r--src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr6
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr8
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.stderr8
-rw-r--r--src/tools/miri/tests/panic/alloc_error_handler_hook.stderr2
-rw-r--r--src/tools/miri/tests/panic/alloc_error_handler_panic.stderr2
-rw-r--r--src/tools/miri/tests/panic/div-by-zero-2.stderr2
-rw-r--r--src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr6
-rw-r--r--src/tools/miri/tests/panic/mir-validation.rs6
-rw-r--r--src/tools/miri/tests/panic/mir-validation.stderr2
-rw-r--r--src/tools/miri/tests/panic/oob_subslice.stderr2
-rw-r--r--src/tools/miri/tests/panic/overflowing-lsh-neg.stderr2
-rw-r--r--src/tools/miri/tests/panic/overflowing-rsh-1.stderr2
-rw-r--r--src/tools/miri/tests/panic/overflowing-rsh-2.stderr2
-rw-r--r--src/tools/miri/tests/panic/panic1.stderr4
-rw-r--r--src/tools/miri/tests/panic/panic2.stderr2
-rw-r--r--src/tools/miri/tests/panic/panic3.stderr2
-rw-r--r--src/tools/miri/tests/panic/panic4.stderr2
-rw-r--r--src/tools/miri/tests/panic/transmute_fat2.stderr2
-rw-r--r--src/tools/miri/tests/pass/panic/catch_panic.stderr22
-rw-r--r--src/tools/miri/tests/pass/panic/concurrent-panic.stderr4
-rw-r--r--src/tools/miri/tests/pass/panic/nested_panic_caught.stderr4
-rw-r--r--src/tools/miri/tests/pass/panic/thread_panic.stderr4
-rw-r--r--src/tools/miri/tests/ui.rs3
-rw-r--r--src/tools/run-make-support/src/diff/mod.rs11
-rw-r--r--src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs32
-rw-r--r--src/tools/run-make-support/src/lib.rs4
-rw-r--r--src/tools/run-make-support/src/targets.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs14
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs3
282 files changed, 5609 insertions, 3268 deletions
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index f6653ed899b..f931aae3c2e 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -84,7 +84,7 @@ impl Step for Std {
             Kind::Check,
         );
 
-        std_cargo(builder, target, stage, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
         if matches!(builder.config.cmd, Subcommand::Fix) {
             // By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
             cargo.arg("--lib");
@@ -125,7 +125,7 @@ impl Step for Std {
             Kind::Check,
         );
 
-        std_cargo(builder, target, build_compiler.stage, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         // Explicitly pass -p for all dependencies krates -- this will force cargo
         // to also check the tests/benches/examples for these crates, rather
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index b119f2dc3ce..93c767bdd25 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -154,7 +154,7 @@ impl Step for Std {
             Kind::Clippy,
         );
 
-        std_cargo(builder, target, compiler.stage, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         for krate in &*self.crates {
             cargo.arg("-p").arg(krate);
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 59541bf12de..e1ee0773107 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -19,7 +19,7 @@ use serde_derive::Deserialize;
 use tracing::{instrument, span};
 
 use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
-use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts};
+use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
 use crate::core::build_steps::{dist, llvm};
 use crate::core::builder;
 use crate::core::builder::{
@@ -269,7 +269,7 @@ impl Step for Std {
                 target,
                 Kind::Build,
             );
-            std_cargo(builder, target, compiler.stage, &mut cargo);
+            std_cargo(builder, target, &mut cargo);
             for krate in &*self.crates {
                 cargo.arg("-p").arg(krate);
             }
@@ -497,7 +497,7 @@ fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
-pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
+pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
     // rustc already ensures that it builds with the minimum deployment
     // target, so ideally we shouldn't need to do anything here.
     //
@@ -645,12 +645,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     // built with bitcode so that the produced rlibs can be used for both LTO
     // builds (which use bitcode) and non-LTO builds (which use object code).
     // So we override the override here!
-    //
-    // But we don't bother for the stage 0 compiler because it's never used
-    // with LTO.
-    if stage >= 1 {
-        cargo.rustflag("-Cembed-bitcode=yes");
-    }
+    cargo.rustflag("-Cembed-bitcode=yes");
+
     if builder.config.rust_lto == RustcLto::Off {
         cargo.rustflag("-Clto=off");
     }
@@ -1131,7 +1127,7 @@ impl Step for Rustc {
             cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
         }
 
-        let _guard = builder.msg_sysroot_tool(
+        let _guard = builder.msg_rustc_tool(
             Kind::Build,
             build_compiler.stage,
             format_args!("compiler artifacts{}", crate_description(&self.crates)),
@@ -1544,9 +1540,8 @@ impl Step for RustcLink {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CodegenBackend {
-    pub target: TargetSelection,
-    pub compiler: Compiler,
-    pub backend: CodegenBackendKind,
+    compilers: RustcPrivateCompilers,
+    backend: CodegenBackendKind,
 }
 
 fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
@@ -1610,8 +1605,11 @@ impl Step for CodegenBackend {
             }
 
             run.builder.ensure(CodegenBackend {
-                target: run.target,
-                compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
+                compilers: RustcPrivateCompilers::new(
+                    run.builder,
+                    run.builder.top_stage,
+                    run.target,
+                ),
                 backend: backend.clone(),
             });
         }
@@ -1624,20 +1622,17 @@ impl Step for CodegenBackend {
             name = "CodegenBackend::run",
             skip_all,
             fields(
-                compiler = ?self.compiler,
-                target = ?self.target,
-                backend = ?self.target,
+                compilers = ?self.compilers,
+                backend = ?self.backend,
             ),
         ),
     )]
     fn run(self, builder: &Builder<'_>) {
-        let compiler = self.compiler;
-        let target = self.target;
         let backend = self.backend;
+        let target = self.compilers.target();
+        let build_compiler = self.compilers.build_compiler();
 
-        builder.ensure(Rustc::new(compiler, target));
-
-        if builder.config.keep_stage.contains(&compiler.stage) {
+        if builder.config.keep_stage.contains(&build_compiler.stage) {
             trace!("`keep-stage` requested");
             builder.info(
                 "WARNING: Using a potentially old codegen backend. \
@@ -1648,17 +1643,11 @@ impl Step for CodegenBackend {
             return;
         }
 
-        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
-        if compiler_to_use != compiler {
-            builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
-            return;
-        }
-
-        let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
+        let out_dir = builder.cargo_out(build_compiler, Mode::Codegen, target);
 
         let mut cargo = builder::Cargo::new(
             builder,
-            compiler,
+            build_compiler,
             Mode::Codegen,
             SourceType::InTree,
             target,
@@ -1679,8 +1668,13 @@ impl Step for CodegenBackend {
 
         let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
 
-        let _guard =
-            builder.msg_build(compiler, format_args!("codegen backend {}", backend.name()), target);
+        let _guard = builder.msg_rustc_tool(
+            Kind::Build,
+            build_compiler.stage,
+            format_args!("codegen backend {}", backend.name()),
+            build_compiler.host,
+            target,
+        );
         let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
         if builder.config.dry_run() {
             return;
@@ -1700,10 +1694,17 @@ impl Step for CodegenBackend {
                 f.display()
             );
         }
-        let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
+        let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend);
         let codegen_backend = codegen_backend.to_str().unwrap();
         t!(stamp.add_stamp(codegen_backend).write());
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::build(&self.backend.crate_name(), self.compilers.target())
+                .built_by(self.compilers.build_compiler()),
+        )
+    }
 }
 
 /// Creates the `codegen-backends` folder for a compiler that's about to be
@@ -2190,8 +2191,10 @@ impl Step for Assemble {
                 continue;
             }
             builder.ensure(CodegenBackend {
-                compiler: build_compiler,
-                target: target_compiler.host,
+                compilers: RustcPrivateCompilers::from_build_and_target_compiler(
+                    build_compiler,
+                    target_compiler,
+                ),
                 backend: backend.clone(),
             });
         }
@@ -2381,15 +2384,19 @@ pub fn run_cargo(
     let mut deps = Vec::new();
     let mut toplevel = Vec::new();
     let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
-        let (filenames, crate_types) = match msg {
+        let (filenames_vec, crate_types) = match msg {
             CargoMessage::CompilerArtifact {
                 filenames,
                 target: CargoTarget { crate_types },
                 ..
-            } => (filenames, crate_types),
+            } => {
+                let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
+                f.sort(); // Sort the filenames
+                (f, crate_types)
+            }
             _ => return,
         };
-        for filename in filenames {
+        for filename in filenames_vec {
             // Skip files like executables
             let mut keep = false;
             if filename.ends_with(".lib")
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4699813abf4..cbbfb6b6a11 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -20,7 +20,7 @@ use object::read::archive::ArchiveFile;
 use tracing::instrument;
 
 use crate::core::build_steps::doc::DocumentationFormat;
-use crate::core::build_steps::tool::{self, Tool};
+use crate::core::build_steps::tool::{self, RustcPrivateCompilers, Tool};
 use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
 use crate::core::build_steps::{compile, llvm};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
@@ -174,36 +174,12 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
     found
 }
 
-fn make_win_dist(
-    rust_root: &Path,
-    plat_root: &Path,
-    target: TargetSelection,
-    builder: &Builder<'_>,
-) {
+fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
     if builder.config.dry_run() {
         return;
     }
 
-    //Ask gcc where it keeps its stuff
-    let mut cmd = command(builder.cc(target));
-    cmd.arg("-print-search-dirs");
-    let gcc_out = cmd.run_capture_stdout(builder).stdout();
-
-    let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
-    let mut lib_path = Vec::new();
-
-    for line in gcc_out.lines() {
-        let idx = line.find(':').unwrap();
-        let key = &line[..idx];
-        let trim_chars: &[_] = &[' ', '='];
-        let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
-
-        if key == "programs" {
-            bin_path.extend(value);
-        } else if key == "libraries" {
-            lib_path.extend(value);
-        }
-    }
+    let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
 
     let compiler = if target == "i686-pc-windows-gnu" {
         "i686-w64-mingw32-gcc.exe"
@@ -213,12 +189,6 @@ fn make_win_dist(
         "gcc.exe"
     };
     let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
-    let mut rustc_dlls = vec!["libwinpthread-1.dll"];
-    if target.starts_with("i686-") {
-        rustc_dlls.push("libgcc_s_dw2-1.dll");
-    } else {
-        rustc_dlls.push("libgcc_s_seh-1.dll");
-    }
 
     // Libraries necessary to link the windows-gnu toolchains.
     // System libraries will be preferred if they are available (see #67429).
@@ -274,25 +244,8 @@ fn make_win_dist(
 
     //Find mingw artifacts we want to bundle
     let target_tools = find_files(&target_tools, &bin_path);
-    let rustc_dlls = find_files(&rustc_dlls, &bin_path);
     let target_libs = find_files(&target_libs, &lib_path);
 
-    // Copy runtime dlls next to rustc.exe
-    let rust_bin_dir = rust_root.join("bin/");
-    fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
-    for src in &rustc_dlls {
-        builder.copy_link_to_folder(src, &rust_bin_dir);
-    }
-
-    if builder.config.lld_enabled {
-        // rust-lld.exe also needs runtime dlls
-        let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
-        fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
-        for src in &rustc_dlls {
-            builder.copy_link_to_folder(src, &rust_target_bin_dir);
-        }
-    }
-
     //Copy platform tools to platform-specific bin directory
     let plat_target_bin_self_contained_dir =
         plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
@@ -320,6 +273,82 @@ fn make_win_dist(
     }
 }
 
+fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
+    if builder.config.dry_run() {
+        return;
+    }
+
+    let (bin_path, libs_path) = get_cc_search_dirs(target, builder);
+
+    let mut rustc_dlls = vec![];
+    // windows-gnu and windows-gnullvm require different runtime libs
+    if target.ends_with("windows-gnu") {
+        rustc_dlls.push("libwinpthread-1.dll");
+        if target.starts_with("i686-") {
+            rustc_dlls.push("libgcc_s_dw2-1.dll");
+        } else {
+            rustc_dlls.push("libgcc_s_seh-1.dll");
+        }
+    } else if target.ends_with("windows-gnullvm") {
+        rustc_dlls.push("libunwind.dll");
+    } else {
+        panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
+    }
+    // FIXME(#144656): Remove this whole `let ...`
+    let bin_path = if target.ends_with("windows-gnullvm") && builder.host_target != target {
+        bin_path
+            .into_iter()
+            .chain(libs_path.iter().map(|path| path.with_file_name("bin")))
+            .collect()
+    } else {
+        bin_path
+    };
+    let rustc_dlls = find_files(&rustc_dlls, &bin_path);
+
+    // Copy runtime dlls next to rustc.exe
+    let rust_bin_dir = rust_root.join("bin/");
+    fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
+    for src in &rustc_dlls {
+        builder.copy_link_to_folder(src, &rust_bin_dir);
+    }
+
+    if builder.config.lld_enabled {
+        // rust-lld.exe also needs runtime dlls
+        let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
+        fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
+        for src in &rustc_dlls {
+            builder.copy_link_to_folder(src, &rust_target_bin_dir);
+        }
+    }
+}
+
+fn get_cc_search_dirs(
+    target: TargetSelection,
+    builder: &Builder<'_>,
+) -> (Vec<PathBuf>, Vec<PathBuf>) {
+    //Ask gcc where it keeps its stuff
+    let mut cmd = command(builder.cc(target));
+    cmd.arg("-print-search-dirs");
+    let gcc_out = cmd.run_capture_stdout(builder).stdout();
+
+    let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
+    let mut lib_path = Vec::new();
+
+    for line in gcc_out.lines() {
+        let idx = line.find(':').unwrap();
+        let key = &line[..idx];
+        let trim_chars: &[_] = &[' ', '='];
+        let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
+
+        if key == "programs" {
+            bin_path.extend(value);
+        } else if key == "libraries" {
+            lib_path.extend(value);
+        }
+    }
+    (bin_path, lib_path)
+}
+
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct Mingw {
     pub host: TargetSelection,
@@ -350,11 +379,7 @@ impl Step for Mingw {
         let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
         tarball.set_product_name("Rust MinGW");
 
-        // The first argument is a "temporary directory" which is just
-        // thrown away (this contains the runtime DLLs included in the rustc package
-        // above) and the second argument is where to place all the MinGW components
-        // (which is what we want).
-        make_win_dist(&tmpdir(builder), tarball.image_dir(), host, builder);
+        make_win_dist(tarball.image_dir(), host, builder);
 
         Some(tarball.generate())
     }
@@ -394,17 +419,14 @@ impl Step for Rustc {
         prepare_image(builder, compiler, tarball.image_dir());
 
         // On MinGW we've got a few runtime DLL dependencies that we need to
-        // include. The first argument to this script is where to put these DLLs
-        // (the image we're creating), and the second argument is a junk directory
-        // to ignore all other MinGW stuff the script creates.
-        //
+        // include.
         // On 32-bit MinGW we're always including a DLL which needs some extra
         // licenses to distribute. On 64-bit MinGW we don't actually distribute
         // anything requiring us to distribute a license, but it's likely the
         // install will *also* include the rust-mingw package, which also needs
         // licenses, so to be safe we just include it here in all MinGW packages.
-        if host.ends_with("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
-            make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder);
+        if host.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
+            runtime_dll_dist(tarball.image_dir(), host, builder);
             tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
         }
 
@@ -425,19 +447,20 @@ impl Step for Rustc {
                 .as_ref()
                 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
             {
-                let rustdoc = builder.rustdoc(compiler);
+                let rustdoc = builder.rustdoc_for_compiler(compiler);
                 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
             }
 
             let ra_proc_macro_srv_compiler =
                 builder.compiler_for(compiler.stage, builder.config.host_target, compiler.host);
-            builder.ensure(compile::Rustc::new(ra_proc_macro_srv_compiler, compiler.host));
+            let compilers = RustcPrivateCompilers::from_build_compiler(
+                builder,
+                ra_proc_macro_srv_compiler,
+                compiler.host,
+            );
 
             if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
-                tool::RustAnalyzerProcMacroSrv {
-                    compiler: ra_proc_macro_srv_compiler,
-                    target: compiler.host,
-                },
+                tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
                 builder.kind,
             ) {
                 let dst = image.join("libexec");
@@ -1172,7 +1195,7 @@ impl Step for PlainSourceTarball {
 
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct Cargo {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -1188,7 +1211,7 @@ impl Step for Cargo {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Cargo {
-            compiler: run.builder.compiler_for(
+            build_compiler: run.builder.compiler_for(
                 run.builder.top_stage,
                 run.builder.config.host_target,
                 run.target,
@@ -1198,12 +1221,10 @@ impl Step for Cargo {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
+        let build_compiler = self.build_compiler;
         let target = self.target;
 
-        builder.ensure(compile::Rustc::new(compiler, target));
-
-        let cargo = builder.ensure(tool::Cargo { compiler, target });
+        let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
         let src = builder.src.join("src/tools/cargo");
         let etc = src.join("src/etc");
 
@@ -1228,7 +1249,7 @@ impl Step for Cargo {
 
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct RustAnalyzer {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -1244,7 +1265,7 @@ impl Step for RustAnalyzer {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RustAnalyzer {
-            compiler: run.builder.compiler_for(
+            build_compiler: run.builder.compiler_for(
                 run.builder.top_stage,
                 run.builder.config.host_target,
                 run.target,
@@ -1254,12 +1275,11 @@ impl Step for RustAnalyzer {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
         let target = self.target;
+        let compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
 
-        builder.ensure(compile::Rustc::new(compiler, target));
-
-        let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target });
+        let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers));
 
         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
         tarball.set_overlay(OverlayKind::RustAnalyzer);
@@ -1270,9 +1290,9 @@ impl Step for RustAnalyzer {
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Clippy {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -1288,7 +1308,7 @@ impl Step for Clippy {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Clippy {
-            compiler: run.builder.compiler_for(
+            build_compiler: run.builder.compiler_for(
                 run.builder.top_stage,
                 run.builder.config.host_target,
                 run.target,
@@ -1298,16 +1318,15 @@ impl Step for Clippy {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
         let target = self.target;
-
-        builder.ensure(compile::Rustc::new(compiler, target));
+        let compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
 
         // Prepare the image directory
         // We expect clippy to build, because we've exited this step above if tool
         // state for clippy isn't testing.
-        let clippy = builder.ensure(tool::Clippy { compiler, target });
-        let cargoclippy = builder.ensure(tool::CargoClippy { compiler, target });
+        let clippy = builder.ensure(tool::Clippy::from_compilers(compilers));
+        let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers));
 
         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
         tarball.set_overlay(OverlayKind::Clippy);
@@ -1319,9 +1338,9 @@ impl Step for Clippy {
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Miri {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -1337,7 +1356,7 @@ impl Step for Miri {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Miri {
-            compiler: run.builder.compiler_for(
+            build_compiler: run.builder.compiler_for(
                 run.builder.top_stage,
                 run.builder.config.host_target,
                 run.target,
@@ -1354,15 +1373,12 @@ impl Step for Miri {
             return None;
         }
 
-        let compiler = self.compiler;
-        let target = self.target;
-
-        builder.ensure(compile::Rustc::new(compiler, target));
-
-        let miri = builder.ensure(tool::Miri { compiler, target });
-        let cargomiri = builder.ensure(tool::CargoMiri { compiler, target });
+        let compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
+        let miri = builder.ensure(tool::Miri::from_compilers(compilers));
+        let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(compilers));
 
-        let mut tarball = Tarball::new(builder, "miri", &target.triple);
+        let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
         tarball.set_overlay(OverlayKind::Miri);
         tarball.is_preview(true);
         tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
@@ -1466,9 +1482,9 @@ impl Step for CodegenBackend {
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Rustfmt {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -1484,7 +1500,7 @@ impl Step for Rustfmt {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Rustfmt {
-            compiler: run.builder.compiler_for(
+            build_compiler: run.builder.compiler_for(
                 run.builder.top_stage,
                 run.builder.config.host_target,
                 run.target,
@@ -1494,14 +1510,13 @@ impl Step for Rustfmt {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
-        let target = self.target;
+        let compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
 
-        builder.ensure(compile::Rustc::new(compiler, target));
+        let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(compilers));
+        let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(compilers));
 
-        let rustfmt = builder.ensure(tool::Rustfmt { compiler, target });
-        let cargofmt = builder.ensure(tool::Cargofmt { compiler, target });
-        let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
+        let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
         tarball.set_overlay(OverlayKind::Rustfmt);
         tarball.is_preview(true);
         tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
@@ -1548,7 +1563,7 @@ impl Step for Extended {
         let mut built_tools = HashSet::new();
         macro_rules! add_component {
             ($name:expr => $step:expr) => {
-                if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
+                if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
                     tarballs.push(tarball);
                     built_tools.insert($name);
                 }
@@ -1568,12 +1583,12 @@ impl Step for Extended {
 
         add_component!("rust-docs" => Docs { host: target });
         add_component!("rust-json-docs" => JsonDocs { host: target });
-        add_component!("cargo" => Cargo { compiler, target });
-        add_component!("rustfmt" => Rustfmt { compiler, target });
-        add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
+        add_component!("cargo" => Cargo { build_compiler: compiler, target });
+        add_component!("rustfmt" => Rustfmt { build_compiler: compiler, target });
+        add_component!("rust-analyzer" => RustAnalyzer { build_compiler: compiler, target });
         add_component!("llvm-components" => LlvmTools { target });
-        add_component!("clippy" => Clippy { compiler, target });
-        add_component!("miri" => Miri { compiler, target });
+        add_component!("clippy" => Clippy { build_compiler: compiler, target });
+        add_component!("miri" => Miri { build_compiler: compiler, target });
         add_component!("analysis" => Analysis { compiler, target });
         add_component!("rustc-codegen-cranelift" => CodegenBackend {
             compiler: builder.compiler(stage, target),
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 37418f640ac..434e9c0977d 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -12,7 +12,9 @@ use std::path::{Path, PathBuf};
 use std::{env, fs, mem};
 
 use crate::core::build_steps::compile;
-use crate::core::build_steps::tool::{self, SourceType, Tool, prepare_tool_cargo};
+use crate::core::build_steps::tool::{
+    self, RustcPrivateCompilers, SourceType, Tool, prepare_tool_cargo,
+};
 use crate::core::builder::{
     self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
     crate_description,
@@ -149,7 +151,7 @@ impl<P: Step> Step for RustbookSrc<P> {
             let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
 
             if let Some(compiler) = self.rustdoc_compiler {
-                let mut rustdoc = builder.rustdoc(compiler);
+                let mut rustdoc = builder.rustdoc_for_compiler(compiler);
                 rustdoc.pop();
                 let old_path = env::var_os("PATH").unwrap_or_default();
                 let new_path =
@@ -365,7 +367,7 @@ impl Step for Standalone {
             }
 
             let html = out.join(filename).with_extension("html");
-            let rustdoc = builder.rustdoc(compiler);
+            let rustdoc = builder.rustdoc_for_compiler(compiler);
             if up_to_date(&path, &html)
                 && up_to_date(&footer, &html)
                 && up_to_date(&favicon, &html)
@@ -463,7 +465,7 @@ impl Step for Releases {
         let html = out.join("releases.html");
         let tmppath = out.join("releases.md");
         let inpath = builder.src.join("RELEASES.md");
-        let rustdoc = builder.rustdoc(compiler);
+        let rustdoc = builder.rustdoc_for_compiler(compiler);
         if !up_to_date(&inpath, &html)
             || !up_to_date(&footer, &html)
             || !up_to_date(&favicon, &html)
@@ -722,7 +724,7 @@ fn doc_std(
     let mut cargo =
         builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, Kind::Doc);
 
-    compile::std_cargo(builder, target, compiler.stage, &mut cargo);
+    compile::std_cargo(builder, target, &mut cargo);
     cargo
         .arg("--no-deps")
         .arg("--target-dir")
@@ -811,7 +813,7 @@ impl Step for Rustc {
         let compiler = builder.compiler(stage, builder.config.host_target);
         builder.std(compiler, builder.config.host_target);
 
-        let _guard = builder.msg_sysroot_tool(
+        let _guard = builder.msg_rustc_tool(
             Kind::Doc,
             stage,
             format!("compiler{}", crate_description(&self.crates)),
@@ -901,6 +903,10 @@ impl Step for Rustc {
             builder.open_in_browser(index);
         }
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::doc("rustc", self.target).stage(self.stage))
+    }
 }
 
 macro_rules! tool_doc {
@@ -1018,6 +1024,10 @@ macro_rules! tool_doc {
                     })?
                 }
             }
+
+            fn metadata(&self) -> Option<StepMetadata> {
+                Some(StepMetadata::doc(stringify!($tool), self.target))
+            }
         }
     }
 }
@@ -1074,9 +1084,9 @@ tool_doc!(
     crates = ["compiletest"]
 );
 
-#[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
-    pub target: TargetSelection,
+    compilers: RustcPrivateCompilers,
 }
 
 impl Step for ErrorIndex {
@@ -1090,17 +1100,29 @@ impl Step for ErrorIndex {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        let target = run.target;
-        run.builder.ensure(ErrorIndex { target });
+        run.builder.ensure(ErrorIndex {
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
+        });
     }
 
     /// Generates the HTML rendered error-index by running the
     /// `error_index_generator` tool.
     fn run(self, builder: &Builder<'_>) {
-        builder.info(&format!("Documenting error index ({})", self.target));
-        let out = builder.doc_out(self.target);
+        builder.info(&format!("Documenting error index ({})", self.compilers.target()));
+        let out = builder.doc_out(self.compilers.target());
         t!(fs::create_dir_all(&out));
-        tool::ErrorIndex::command(builder).arg("html").arg(out).arg(&builder.version).run(builder);
+        tool::ErrorIndex::command(builder, self.compilers)
+            .arg("html")
+            .arg(out)
+            .arg(&builder.version)
+            .run(builder);
+    }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::doc("error-index", self.compilers.target())
+                .built_by(self.compilers.build_compiler()),
+        )
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 4513a138e19..f628330e9ed 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -215,13 +215,13 @@ install!((self, builder, _config),
     };
     Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, {
         let tarball = builder
-            .ensure(dist::Cargo { compiler: self.compiler, target: self.target })
+            .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target })
             .expect("missing cargo");
         install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
     };
     RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) =
-            builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
+            builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target })
         {
             install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
         } else {
@@ -232,12 +232,12 @@ install!((self, builder, _config),
     };
     Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, {
         let tarball = builder
-            .ensure(dist::Clippy { compiler: self.compiler, target: self.target })
+            .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target })
             .expect("missing clippy");
         install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
     };
     Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
-        if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
+        if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) {
             install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
         } else {
             // Miri is only available on nightly
@@ -257,7 +257,7 @@ install!((self, builder, _config),
     };
     Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Rustfmt {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target
         }) {
             install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index b2056f5cf37..721ba6ca459 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -1528,8 +1528,12 @@ impl Step for Libunwind {
 
         // FIXME: https://github.com/alexcrichton/cc-rs/issues/545#issuecomment-679242845
         let mut count = 0;
-        for entry in fs::read_dir(&out_dir).unwrap() {
-            let file = entry.unwrap().path().canonicalize().unwrap();
+        let mut files = fs::read_dir(&out_dir)
+            .unwrap()
+            .map(|entry| entry.unwrap().path().canonicalize().unwrap())
+            .collect::<Vec<_>>();
+        files.sort();
+        for file in files {
             if file.is_file() && file.extension() == Some(OsStr::new("o")) {
                 // Object file name without the hash prefix is "Unwind-EHABI", "Unwind-seh" or "libunwind".
                 let base_name = unhashed_basename(&file);
diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs
index 4d61b38c876..108b7f90c14 100644
--- a/src/bootstrap/src/core/build_steps/perf.rs
+++ b/src/bootstrap/src/core/build_steps/perf.rs
@@ -157,7 +157,7 @@ Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#);
     if let Some(opts) = args.cmd.shared_opts()
         && opts.profiles.contains(&Profile::Doc)
     {
-        builder.ensure(Rustdoc { compiler });
+        builder.ensure(Rustdoc { target_compiler: compiler });
     }
 
     let sysroot = builder.ensure(Sysroot::new(compiler));
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index b2293fdd9b5..962dd372849 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -9,7 +9,7 @@ use clap_complete::{Generator, shells};
 
 use crate::core::build_steps::dist::distdir;
 use crate::core::build_steps::test;
-use crate::core::build_steps::tool::{self, SourceType, Tool};
+use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool};
 use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
@@ -135,13 +135,13 @@ impl Step for Miri {
         }
 
         // This compiler runs on the host, we'll just use it for the target.
-        let target_compiler = builder.compiler(stage, target);
-        let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target });
-        // Rustc tools are off by one stage, so use the build compiler to run miri.
+        let compilers = RustcPrivateCompilers::new(builder, stage, target);
+        let miri_build = builder.ensure(tool::Miri::from_compilers(compilers));
         let host_compiler = miri_build.build_compiler;
 
         // Get a target sysroot for Miri.
-        let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
+        let miri_sysroot =
+            test::Miri::build_miri_sysroot(builder, compilers.target_compiler(), target);
 
         // # Run miri.
         // Running it via `cargo run` as that figures out the right dylib path.
@@ -465,8 +465,8 @@ impl Step for Rustfmt {
             std::process::exit(1);
         }
 
-        let compiler = builder.compiler(stage, host);
-        let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host });
+        let compilers = RustcPrivateCompilers::new(builder, stage, host);
+        let rustfmt_build = builder.ensure(tool::Rustfmt::from_compilers(compilers));
 
         let mut rustfmt = tool::prepare_tool_cargo(
             builder,
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 8bee00a9c13..66332c0b3e8 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -4,10 +4,12 @@
 //! However, this contains ~all test parts we expect people to be able to build and run locally.
 
 use std::collections::HashSet;
+use std::env::split_paths;
 use std::ffi::{OsStr, OsString};
 use std::path::{Path, PathBuf};
 use std::{env, fs, iter};
 
+use build_helper::exit;
 #[cfg(feature = "tracing")]
 use tracing::instrument;
 
@@ -17,7 +19,10 @@ use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
 use crate::core::build_steps::llvm::get_llvm_version;
 use crate::core::build_steps::run::get_completion_paths;
 use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
-use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool};
+use crate::core::build_steps::tool::{
+    self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType, Tool, ToolTargetBuildMode,
+    get_tool_target_compiler,
+};
 use crate::core::build_steps::toolstate::ToolState;
 use crate::core::build_steps::{compile, dist, llvm};
 use crate::core::builder::{
@@ -29,8 +34,8 @@ use crate::core::config::flags::{Subcommand, get_completion};
 use crate::utils::build_stamp::{self, BuildStamp};
 use crate::utils::exec::{BootstrapCommand, command};
 use crate::utils::helpers::{
-    self, LldThreads, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, linker_args,
-    linker_flags, t, target_supports_cranelift_backend, up_to_date,
+    self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
+    linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
 };
 use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
 use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, envify};
@@ -226,7 +231,7 @@ impl Step for HtmlCheck {
 /// order to test cargo.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargotest {
-    stage: u32,
+    build_compiler: Compiler,
     host: TargetSelection,
 }
 
@@ -239,7 +244,19 @@ impl Step for Cargotest {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Cargotest { stage: run.builder.top_stage, host: run.target });
+        if run.builder.top_stage == 0 {
+            eprintln!(
+                "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
+            );
+            exit!(1);
+        }
+        // We want to build cargo stage N (where N == top_stage), and rustc stage N,
+        // and test both of these together.
+        // So we need to get a build compiler stage N-1 to build the stage N components.
+        run.builder.ensure(Cargotest {
+            build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
+            host: run.target,
+        });
     }
 
     /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
@@ -247,9 +264,19 @@ impl Step for Cargotest {
     /// This tool in `src/tools` will check out a few Rust projects and run `cargo
     /// test` to ensure that we don't regress the test suites there.
     fn run(self, builder: &Builder<'_>) {
-        let compiler = builder.compiler(self.stage, self.host);
-        builder.ensure(compile::Rustc::new(compiler, compiler.host));
-        let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host });
+        // cargotest's staging has several pieces:
+        // consider ./x test cargotest --stage=2.
+        //
+        // The test goal is to exercise a (stage 2 cargo, stage 2 rustc) pair through a stage 2
+        // cargotest tool.
+        // To produce the stage 2 cargo and cargotest, we need to do so with the stage 1 rustc and std.
+        // Importantly, the stage 2 rustc being tested (`tested_compiler`) via stage 2 cargotest is
+        // the rustc built by an earlier stage 1 rustc (the build_compiler). These are two different
+        // compilers!
+        let cargo =
+            builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
+        let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
+        builder.std(tested_compiler, self.host);
 
         // Note that this is a short, cryptic, and not scoped directory name. This
         // is currently to minimize the length of path on Windows where we otherwise
@@ -262,23 +289,22 @@ impl Step for Cargotest {
         cmd.arg(&cargo.tool_path)
             .arg(&out_dir)
             .args(builder.config.test_args())
-            .env("RUSTC", builder.rustc(compiler))
-            .env("RUSTDOC", builder.rustdoc(compiler));
-        add_rustdoc_cargo_linker_args(
-            &mut cmd,
-            builder,
-            compiler.host,
-            LldThreads::No,
-            compiler.stage,
-        );
+            .env("RUSTC", builder.rustc(tested_compiler))
+            .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
+        add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
         cmd.delay_failure().run(builder);
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
+    }
 }
 
 /// Runs `cargo test` for cargo itself.
+/// We label these tests as "cargo self-tests".
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargo {
-    stage: u32,
+    build_compiler: Compiler,
     host: TargetSelection,
 }
 
@@ -295,35 +321,33 @@ impl Step for Cargo {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2
-        // as tests for this step don't work with a lower stage.
-        let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
-            run.builder.top_stage
-        } else {
-            2
-        };
-
-        run.builder.ensure(Cargo { stage, host: run.target });
+        run.builder.ensure(Cargo {
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
+            ),
+            host: run.target,
+        });
     }
 
     /// Runs `cargo test` for `cargo` packaged with Rust.
     fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
-
-        if stage < 2 {
-            eprintln!("WARNING: cargo tests on stage {stage} may not behave well.");
-            eprintln!("HELP: consider using stage 2");
-        }
-
-        let compiler = builder.compiler(stage, self.host);
-
-        let cargo = builder.ensure(tool::Cargo { compiler, target: self.host });
-        let compiler = cargo.build_compiler;
+        // When we do a "stage 1 cargo self-test", it means that we test the stage 1 rustc
+        // using stage 1 cargo. So we actually build cargo using the stage 0 compiler, and then
+        // run its tests against the stage 1 compiler (called `tested_compiler` below).
+        builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
+
+        let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
+        builder.std(tested_compiler, self.host);
+        // We also need to build rustdoc for cargo tests
+        // It will be located in the bindir of `tested_compiler`, so we don't need to explicitly
+        // pass its path to Cargo.
+        builder.rustdoc_for_compiler(tested_compiler);
 
         let cargo = tool::prepare_tool_cargo(
             builder,
-            compiler,
-            Mode::ToolRustc,
+            self.build_compiler,
+            Mode::ToolTarget,
             self.host,
             Kind::Test,
             Self::CRATE_PATH,
@@ -340,7 +364,25 @@ impl Step for Cargo {
         // Forcibly disable tests using nightly features since any changes to
         // those features won't be able to land.
         cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
-        cargo.env("PATH", path_for_cargo(builder, compiler));
+
+        // Configure PATH to find the right rustc. NB. we have to use PATH
+        // and not RUSTC because the Cargo test suite has tests that will
+        // fail if rustc is not spelled `rustc`.
+        cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
+
+        // The `cargo` command configured above has dylib dir path set to the `build_compiler`'s
+        // libdir. That causes issues in cargo test, because the programs that cargo compiles are
+        // incorrectly picking that libdir, even though they should be picking the
+        // `tested_compiler`'s libdir. We thus have to override the precedence here.
+        let mut existing_dylib_paths = cargo
+            .get_envs()
+            .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
+            .and_then(|(_, v)| v)
+            .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
+            .unwrap_or_default();
+        existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
+        add_dylib_path(existing_dylib_paths, &mut cargo);
+
         // Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is
         // relative to. Cargo no longer sets this env var, so we have to do that. This has to be the
         // same value as `-Zroot-dir`.
@@ -352,7 +394,7 @@ impl Step for Cargo {
                 crates: vec!["cargo".into()],
                 target: self.host.triple.to_string(),
                 host: self.host.triple.to_string(),
-                stage,
+                stage: self.build_compiler.stage + 1,
             },
             builder,
         );
@@ -364,8 +406,7 @@ impl Step for Cargo {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct RustAnalyzer {
-    stage: u32,
-    host: TargetSelection,
+    compilers: RustcPrivateCompilers,
 }
 
 impl Step for RustAnalyzer {
@@ -378,19 +419,18 @@ impl Step for RustAnalyzer {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Self { stage: run.builder.top_stage, host: run.target });
+        run.builder.ensure(Self {
+            compilers: RustcPrivateCompilers::new(
+                run.builder,
+                run.builder.top_stage,
+                run.builder.host_target,
+            ),
+        });
     }
 
     /// Runs `cargo test` for rust-analyzer
     fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
-        let host = self.host;
-        let compiler = builder.compiler(stage, host);
-        let compiler = tool::get_tool_rustc_compiler(builder, compiler);
-
-        // We don't need to build the whole Rust Analyzer for the proc-macro-srv test suite,
-        // but we do need the standard library to be present.
-        builder.ensure(compile::Rustc::new(compiler, host));
+        let host = self.compilers.target();
 
         let workspace_path = "src/tools/rust-analyzer";
         // until the whole RA test suite runs on `i686`, we only run
@@ -398,7 +438,7 @@ impl Step for RustAnalyzer {
         let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
         let mut cargo = tool::prepare_tool_cargo(
             builder,
-            compiler,
+            self.compilers.build_compiler(),
             Mode::ToolRustc,
             host,
             Kind::Test,
@@ -425,8 +465,7 @@ impl Step for RustAnalyzer {
 /// Runs `cargo test` for rustfmt.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Rustfmt {
-    stage: u32,
-    host: TargetSelection,
+    compilers: RustcPrivateCompilers,
 }
 
 impl Step for Rustfmt {
@@ -438,36 +477,39 @@ impl Step for Rustfmt {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target });
+        run.builder.ensure(Rustfmt {
+            compilers: RustcPrivateCompilers::new(
+                run.builder,
+                run.builder.top_stage,
+                run.builder.host_target,
+            ),
+        });
     }
 
     /// Runs `cargo test` for rustfmt.
     fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
-        let host = self.host;
-        let compiler = builder.compiler(stage, host);
-
-        let tool_result = builder.ensure(tool::Rustfmt { compiler, target: self.host });
-        let compiler = tool_result.build_compiler;
+        let tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
+        let build_compiler = tool_result.build_compiler;
+        let target = self.compilers.target();
 
         let mut cargo = tool::prepare_tool_cargo(
             builder,
-            compiler,
+            build_compiler,
             Mode::ToolRustc,
-            host,
+            target,
             Kind::Test,
             "src/tools/rustfmt",
             SourceType::InTree,
             &[],
         );
 
-        let dir = testdir(builder, compiler.host);
+        let dir = testdir(builder, target);
         t!(fs::create_dir_all(&dir));
         cargo.env("RUSTFMT_TEST_DIR", dir);
 
         cargo.add_rustc_lib_path(builder);
 
-        run_cargo_test(cargo, &[], &[], "rustfmt", host, builder);
+        run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
     }
 }
 
@@ -542,12 +584,14 @@ impl Step for Miri {
         }
 
         // This compiler runs on the host, we'll just use it for the target.
-        let target_compiler = builder.compiler(stage, host);
+        let compilers = RustcPrivateCompilers::new(builder, stage, host);
 
         // Build our tools.
-        let miri = builder.ensure(tool::Miri { compiler: target_compiler, target: host });
+        let miri = builder.ensure(tool::Miri::from_compilers(compilers));
         // the ui tests also assume cargo-miri has been built
-        builder.ensure(tool::CargoMiri { compiler: target_compiler, target: host });
+        builder.ensure(tool::CargoMiri::from_compilers(compilers));
+
+        let target_compiler = compilers.target_compiler();
 
         // We also need sysroots, for Miri and for the host (the latter for build scripts).
         // This is for the tests so everything is done with the target compiler.
@@ -599,7 +643,7 @@ impl Step for Miri {
         cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
 
         {
-            let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target);
+            let _guard = builder.msg_rustc_tool(Kind::Test, stage, "miri", host, target);
             let _time = helpers::timeit(builder);
             cargo.run(builder);
         }
@@ -615,7 +659,7 @@ impl Step for Miri {
             cargo.args(["tests/pass", "tests/panic"]);
 
             {
-                let _guard = builder.msg_sysroot_tool(
+                let _guard = builder.msg_rustc_tool(
                     Kind::Test,
                     stage,
                     "miri (mir-opt-level 4)",
@@ -692,7 +736,7 @@ impl Step for CargoMiri {
         // Finally, run everything.
         let mut cargo = BootstrapCommand::from(cargo);
         {
-            let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target);
+            let _guard = builder.msg_rustc_tool(Kind::Test, stage, "cargo-miri", host, target);
             let _time = helpers::timeit(builder);
             cargo.run(builder);
         }
@@ -762,7 +806,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Clippy {
-    host: TargetSelection,
+    compilers: RustcPrivateCompilers,
 }
 
 impl Step for Clippy {
@@ -775,23 +819,30 @@ impl Step for Clippy {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Clippy { host: run.target });
+        run.builder.ensure(Clippy {
+            compilers: RustcPrivateCompilers::new(
+                run.builder,
+                run.builder.top_stage,
+                run.builder.host_target,
+            ),
+        });
     }
 
     /// Runs `cargo test` for clippy.
     fn run(self, builder: &Builder<'_>) {
-        let stage = builder.top_stage;
-        let host = self.host;
+        let host = self.compilers.target();
+
         // We need to carefully distinguish the compiler that builds clippy, and the compiler
         // that is linked into the clippy being tested. `target_compiler` is the latter,
         // and it must also be used by clippy's test runner to build tests and their dependencies.
-        let target_compiler = builder.compiler(stage, host);
+        let compilers = self.compilers;
+        let target_compiler = compilers.target_compiler();
 
-        let tool_result = builder.ensure(tool::Clippy { compiler: target_compiler, target: host });
-        let tool_compiler = tool_result.build_compiler;
+        let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
+        let build_compiler = tool_result.build_compiler;
         let mut cargo = tool::prepare_tool_cargo(
             builder,
-            tool_compiler,
+            build_compiler,
             Mode::ToolRustc,
             host,
             Kind::Test,
@@ -800,9 +851,10 @@ impl Step for Clippy {
             &[],
         );
 
-        cargo.env("RUSTC_TEST_SUITE", builder.rustc(tool_compiler));
-        cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(tool_compiler));
-        let host_libs = builder.stage_out(tool_compiler, Mode::ToolRustc).join(builder.cargo_dir());
+        cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
+        cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
+        let host_libs =
+            builder.stage_out(build_compiler, Mode::ToolRustc).join(builder.cargo_dir());
         cargo.env("HOST_LIBS", host_libs);
 
         // Build the standard library that the tests can use.
@@ -831,8 +883,7 @@ impl Step for Clippy {
         cargo.add_rustc_lib_path(builder);
         let cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
 
-        let _guard =
-            builder.msg_sysroot_tool(Kind::Test, tool_compiler.stage, "clippy", host, host);
+        let _guard = builder.msg_rustc_tool(Kind::Test, build_compiler.stage, "clippy", host, host);
 
         // Clippy reports errors if it blessed the outputs
         if cargo.allow_failure().run(builder) {
@@ -846,10 +897,7 @@ impl Step for Clippy {
     }
 }
 
-fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
-    // Configure PATH to find the right rustc. NB. we have to use PATH
-    // and not RUSTC because the Cargo test suite has tests that will
-    // fail if rustc is not spelled `rustc`.
+fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
     let path = builder.sysroot(compiler).join("bin");
     let old_path = env::var_os("PATH").unwrap_or_default();
     env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
@@ -884,9 +932,9 @@ impl Step for RustdocTheme {
             .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
             .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host))
             .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
-            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
+            .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.compiler))
             .env("RUSTC_BOOTSTRAP", "1");
-        cmd.args(linker_args(builder, self.compiler.host, LldThreads::No, self.compiler.stage));
+        cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
 
         cmd.delay_failure().run(builder);
     }
@@ -1043,7 +1091,11 @@ impl Step for RustdocGUI {
         let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
 
         let out_dir = builder.test_out(self.target).join("rustdoc-gui");
-        build_stamp::clear_if_dirty(builder, &out_dir, &builder.rustdoc(self.compiler));
+        build_stamp::clear_if_dirty(
+            builder,
+            &out_dir,
+            &builder.rustdoc_for_compiler(self.compiler),
+        );
 
         if let Some(src) = builder.config.src.to_str() {
             cmd.arg("--rust-src").arg(src);
@@ -1059,16 +1111,10 @@ impl Step for RustdocGUI {
 
         cmd.arg("--jobs").arg(builder.jobs().to_string());
 
-        cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
+        cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.compiler))
             .env("RUSTC", builder.rustc(self.compiler));
 
-        add_rustdoc_cargo_linker_args(
-            &mut cmd,
-            builder,
-            self.compiler.host,
-            LldThreads::No,
-            self.compiler.stage,
-        );
+        add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
 
         for path in &builder.paths {
             if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
@@ -1095,7 +1141,7 @@ impl Step for RustdocGUI {
         }
 
         let _time = helpers::timeit(builder);
-        let _guard = builder.msg_sysroot_tool(
+        let _guard = builder.msg_rustc_tool(
             Kind::Test,
             self.compiler.stage,
             "rustdoc-gui",
@@ -1737,7 +1783,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                 // If we're using `--stage 0`, we should provide the bootstrap cargo.
                 builder.initial_cargo.clone()
             } else {
-                builder.ensure(tool::Cargo { compiler, target: compiler.host }).tool_path
+                builder.ensure(tool::Cargo::from_build_compiler(compiler, compiler.host)).tool_path
             };
 
             cmd.arg("--cargo-path").arg(cargo_path);
@@ -1756,7 +1802,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             || mode == "rustdoc-json"
             || suite == "coverage-run-rustdoc"
         {
-            cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
+            cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(compiler));
         }
 
         if mode == "rustdoc-json" {
@@ -1893,7 +1939,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         let mut hostflags = flags.clone();
-        hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No, compiler.stage));
+        hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
 
         let mut targetflags = flags;
 
@@ -2272,7 +2318,7 @@ impl BookTest {
 
         // mdbook just executes a binary named "rustdoc", so we need to update
         // PATH so that it points to our rustdoc.
-        let mut rustdoc_path = builder.rustdoc(compiler);
+        let mut rustdoc_path = builder.rustdoc_for_compiler(compiler);
         rustdoc_path.pop();
         let old_path = env::var_os("PATH").unwrap_or_default();
         let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
@@ -2456,7 +2502,7 @@ test_book!(
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct ErrorIndex {
-    compiler: Compiler,
+    compilers: RustcPrivateCompilers,
 }
 
 impl Step for ErrorIndex {
@@ -2474,8 +2520,12 @@ impl Step for ErrorIndex {
         // error_index_generator depends on librustdoc. Use the compiler that
         // is normally used to build rustdoc for other tests (like compiletest
         // tests in tests/rustdoc) so that it shares the same artifacts.
-        let compiler = run.builder.compiler(run.builder.top_stage, run.builder.config.host_target);
-        run.builder.ensure(ErrorIndex { compiler });
+        let compilers = RustcPrivateCompilers::new(
+            run.builder,
+            run.builder.top_stage,
+            run.builder.config.host_target,
+        );
+        run.builder.ensure(ErrorIndex { compilers });
     }
 
     /// Runs the error index generator tool to execute the tests located in the error
@@ -2485,24 +2535,30 @@ impl Step for ErrorIndex {
     /// generate a markdown file from the error indexes of the code base which is
     /// then passed to `rustdoc --test`.
     fn run(self, builder: &Builder<'_>) {
-        let compiler = self.compiler;
+        // The compiler that we are testing
+        let target_compiler = self.compilers.target_compiler();
 
-        let dir = testdir(builder, compiler.host);
+        let dir = testdir(builder, target_compiler.host);
         t!(fs::create_dir_all(&dir));
         let output = dir.join("error-index.md");
 
-        let mut tool = tool::ErrorIndex::command(builder);
+        let mut tool = tool::ErrorIndex::command(builder, self.compilers);
         tool.arg("markdown").arg(&output);
 
-        let guard =
-            builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
+        let guard = builder.msg(
+            Kind::Test,
+            target_compiler.stage,
+            "error-index",
+            target_compiler.host,
+            target_compiler.host,
+        );
         let _time = helpers::timeit(builder);
         tool.run_capture(builder);
         drop(guard);
         // The tests themselves need to link to std, so make sure it is
         // available.
-        builder.std(compiler, compiler.host);
-        markdown_test(builder, compiler, &output);
+        builder.std(target_compiler, target_compiler.host);
+        markdown_test(builder, target_compiler, &output);
     }
 }
 
@@ -2595,7 +2651,7 @@ fn run_cargo_test<'a>(
     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)
+        builder.msg_rustc_tool(Kind::Test, compiler.stage, what, compiler.host, target)
     });
 
     #[cfg(feature = "build-metrics")]
@@ -2800,7 +2856,7 @@ impl Step for Crate {
                         .arg("--manifest-path")
                         .arg(builder.src.join("library/sysroot/Cargo.toml"));
                 } else {
-                    compile::std_cargo(builder, target, compiler.stage, &mut cargo);
+                    compile::std_cargo(builder, target, &mut cargo);
                 }
             }
             Mode::Rustc => {
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index f5fa33b98f3..7b0ef942abe 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -71,13 +71,9 @@ impl Builder<'_> {
     ) -> Option<gha::Group> {
         match mode {
             // depends on compiler stage, different to host compiler
-            Mode::ToolRustc => self.msg_sysroot_tool(
-                kind,
-                build_stage,
-                format_args!("tool {tool}"),
-                *host,
-                *target,
-            ),
+            Mode::ToolRustc => {
+                self.msg_rustc_tool(kind, build_stage, format_args!("tool {tool}"), *host, *target)
+            }
             // doesn't depend on compiler, same as host compiler
             _ => self.msg(kind, build_stage, format_args!("tool {tool}"), *host, *target),
         }
@@ -90,11 +86,8 @@ impl Builder<'_> {
 pub struct ToolBuildResult {
     /// 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`.
+    /// Compiler used to build the tool.
     pub build_compiler: Compiler,
-    /// Target compiler passed to `Step`.
-    pub target_compiler: Compiler,
 }
 
 impl Step for ToolBuild {
@@ -108,22 +101,15 @@ impl Step for ToolBuild {
     ///
     /// This will build the specified tool with the specified `host` compiler in
     /// `stage` into the normal cargo output directory.
-    fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
+    fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         let target = self.target;
         let mut tool = self.tool;
         let path = self.path;
 
-        let target_compiler = self.build_compiler;
-        self.build_compiler = if self.mode == Mode::ToolRustc {
-            get_tool_rustc_compiler(builder, self.build_compiler)
-        } else {
-            self.build_compiler
-        };
-
         match self.mode {
             Mode::ToolRustc => {
-                // If compiler was forced, its artifacts should have been prepared earlier.
-                if !self.build_compiler.is_forced_compiler() {
+                // FIXME: remove this, it's only needed for download-rustc...
+                if !self.build_compiler.is_forced_compiler() && builder.download_rustc() {
                     builder.std(self.build_compiler, self.build_compiler.host);
                     builder.ensure(compile::Rustc::new(self.build_compiler, target));
                 }
@@ -184,8 +170,7 @@ impl Step for ToolBuild {
             Kind::Build,
             self.mode,
             self.tool,
-            // A stage N tool is built with the stage N-1 compiler.
-            self.build_compiler.stage + 1,
+            self.build_compiler.stage,
             &self.build_compiler.host,
             &self.target,
         );
@@ -216,7 +201,7 @@ impl Step for ToolBuild {
                     .join(format!("lib{tool}.rlib")),
             };
 
-            ToolBuildResult { tool_path, build_compiler: self.build_compiler, target_compiler }
+            ToolBuildResult { tool_path, build_compiler: self.build_compiler }
         }
     }
 }
@@ -346,27 +331,6 @@ pub fn prepare_tool_cargo(
     cargo
 }
 
-/// Handle stage-off logic for `ToolRustc` tools when necessary.
-pub(crate) fn get_tool_rustc_compiler(
-    builder: &Builder<'_>,
-    target_compiler: Compiler,
-) -> Compiler {
-    if target_compiler.is_forced_compiler() {
-        return target_compiler;
-    }
-
-    if builder.download_rustc() && target_compiler.stage == 1 {
-        // We shouldn't drop to stage0 compiler when using CI rustc.
-        return builder.compiler(1, builder.config.host_target);
-    }
-
-    // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
-    // we'd have stageN/bin/rustc and stageN/bin/$rustc_tool be effectively different stage
-    // compilers, which isn't what we want. Rustc tools should be linked in the same way as the
-    // compiler it's paired with, so it must be built with the previous stage compiler.
-    builder.compiler(target_compiler.stage.saturating_sub(1), builder.config.host_target)
-}
-
 /// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it.
 /// The compiler stage is automatically bumped if we need to cross-compile a stage 1 tool.
 pub enum ToolTargetBuildMode {
@@ -624,20 +588,20 @@ impl Step for RustcPerf {
     }
 }
 
-#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
-    pub compiler: Compiler,
+    compilers: RustcPrivateCompilers,
 }
 
 impl ErrorIndex {
-    pub fn command(builder: &Builder<'_>) -> BootstrapCommand {
+    pub fn command(builder: &Builder<'_>, compilers: RustcPrivateCompilers) -> BootstrapCommand {
         // Error-index-generator links with the rustdoc library, so we need to add `rustc_lib_paths`
         // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc.
-        let host = builder.config.host_target;
-        let compiler = builder.compiler_for(builder.top_stage, host, host);
-        let mut cmd = command(builder.ensure(ErrorIndex { compiler }).tool_path);
-        let mut dylib_paths = builder.rustc_lib_paths(compiler);
-        dylib_paths.push(builder.sysroot_target_libdir(compiler, compiler.host));
+        let mut cmd = command(builder.ensure(ErrorIndex { compilers }).tool_path);
+
+        let target_compiler = compilers.target_compiler();
+        let mut dylib_paths = builder.rustc_lib_paths(target_compiler);
+        dylib_paths.push(builder.sysroot_target_libdir(target_compiler, target_compiler.host));
         add_dylib_path(dylib_paths, &mut cmd);
         cmd
     }
@@ -656,14 +620,19 @@ impl Step for ErrorIndex {
         // src/tools/error-index-generator` which almost nobody does.
         // Normally, `x.py test` or `x.py doc` will use the
         // `ErrorIndex::command` function instead.
-        let compiler = run.builder.compiler(run.builder.top_stage, run.builder.config.host_target);
-        run.builder.ensure(ErrorIndex { compiler });
+        run.builder.ensure(ErrorIndex {
+            compilers: RustcPrivateCompilers::new(
+                run.builder,
+                run.builder.top_stage,
+                run.builder.host_target,
+            ),
+        });
     }
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.ensure(ToolBuild {
-            build_compiler: self.compiler,
-            target: self.compiler.host,
+            build_compiler: self.compilers.build_compiler,
+            target: self.compilers.target(),
             tool: "error_index_generator",
             mode: Mode::ToolRustc,
             path: "src/tools/error_index_generator",
@@ -674,6 +643,13 @@ impl Step for ErrorIndex {
             artifact_kind: ToolArtifactKind::Binary,
         })
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::build("error-index", self.compilers.target())
+                .built_by(self.compilers.build_compiler),
+        )
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -719,15 +695,21 @@ impl Step for RemoteTestServer {
     }
 }
 
-#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
+/// Represents `Rustdoc` that either comes from the external stage0 sysroot or that is built
+/// locally.
+/// Rustdoc is special, because it both essentially corresponds to a `Compiler` (that can be
+/// externally provided), but also to a `ToolRustc` tool.
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Rustdoc {
-    /// This should only ever be 0 or 2.
-    /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here.
-    pub compiler: Compiler,
+    /// If the stage of `target_compiler` is `0`, then rustdoc is externally provided.
+    /// Otherwise it is built locally.
+    pub target_compiler: Compiler,
 }
 
 impl Step for Rustdoc {
-    type Output = ToolBuildResult;
+    /// Path to the built rustdoc binary.
+    type Output = PathBuf;
+
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -736,26 +718,25 @@ impl Step for Rustdoc {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder
-            .ensure(Rustdoc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
+        run.builder.ensure(Rustdoc {
+            target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
+        });
     }
 
-    fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
-        let target_compiler = self.compiler;
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let target_compiler = self.target_compiler;
         let target = target_compiler.host;
 
+        // If stage is 0, we use a prebuilt rustdoc from stage0
         if target_compiler.stage == 0 {
             if !target_compiler.is_snapshot(builder) {
                 panic!("rustdoc in stage 0 must be snapshot rustdoc");
             }
 
-            return ToolBuildResult {
-                tool_path: builder.initial_rustdoc.clone(),
-                build_compiler: target_compiler,
-                target_compiler,
-            };
+            return builder.initial_rustdoc.clone();
         }
 
+        // If stage is higher, we build rustdoc instead
         let bin_rustdoc = || {
             let sysroot = builder.sysroot(target_compiler);
             let bindir = sysroot.join("bin");
@@ -767,10 +748,7 @@ impl Step for Rustdoc {
 
         // If CI rustc is enabled and we haven't modified the rustdoc sources,
         // use the precompiled rustdoc from CI rustc's sysroot to speed up bootstrapping.
-        if builder.download_rustc()
-            && target_compiler.stage > 0
-            && builder.rust_info().is_managed_git_subrepository()
-        {
+        if builder.download_rustc() && builder.rust_info().is_managed_git_subrepository() {
             let files_to_track = &["src/librustdoc", "src/tools/rustdoc", "src/rustdoc-json-types"];
 
             // Check if unchanged
@@ -783,12 +761,7 @@ impl Step for Rustdoc {
 
                 let bin_rustdoc = bin_rustdoc();
                 builder.copy_link(&precompiled_rustdoc, &bin_rustdoc, FileType::Executable);
-
-                return ToolBuildResult {
-                    tool_path: bin_rustdoc,
-                    build_compiler: target_compiler,
-                    target_compiler,
-                };
+                return bin_rustdoc;
             }
         }
 
@@ -804,9 +777,10 @@ impl Step for Rustdoc {
             extra_features.push("jemalloc".to_string());
         }
 
-        let ToolBuildResult { tool_path, build_compiler, target_compiler } =
-            builder.ensure(ToolBuild {
-                build_compiler: target_compiler,
+        let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
+        let tool_path = builder
+            .ensure(ToolBuild {
+                build_compiler: compilers.build_compiler,
                 target,
                 // 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"
@@ -819,38 +793,41 @@ impl Step for Rustdoc {
                 allow_features: "",
                 cargo_args: Vec::new(),
                 artifact_kind: ToolArtifactKind::Binary,
-            });
-
-        // don't create a stage0-sysroot/bin directory.
-        if target_compiler.stage > 0 {
-            if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None {
-                // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into
-                // our final binaries
-                compile::strip_debug(builder, target, &tool_path);
-            }
-            let bin_rustdoc = bin_rustdoc();
-            builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable);
-            ToolBuildResult { tool_path: bin_rustdoc, build_compiler, target_compiler }
-        } else {
-            ToolBuildResult { tool_path, build_compiler, target_compiler }
+            })
+            .tool_path;
+
+        if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None {
+            // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into
+            // our final binaries
+            compile::strip_debug(builder, target, &tool_path);
         }
+        let bin_rustdoc = bin_rustdoc();
+        builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable);
+        bin_rustdoc
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
         Some(
-            StepMetadata::build("rustdoc", self.compiler.host)
-                // rustdoc is ToolRustc, so stage N rustdoc is built by stage N-1 rustc
-                // FIXME: make this stage deduction automatic somehow
-                // FIXME: log the compiler that actually built ToolRustc steps
-                .stage(self.compiler.stage.saturating_sub(1)),
+            StepMetadata::build("rustdoc", self.target_compiler.host)
+                .stage(self.target_compiler.stage),
         )
     }
 }
 
+/// Builds the cargo tool.
+/// Note that it can be built using a stable compiler.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Cargo {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    build_compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl Cargo {
+    /// Returns `Cargo` that will be **compiled** by the passed compiler, for the given
+    /// `target`.
+    pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
+        Self { build_compiler, target }
+    }
 }
 
 impl Step for Cargo {
@@ -865,7 +842,10 @@ impl Step for Cargo {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Cargo {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
+            ),
             target: run.target,
         });
     }
@@ -873,19 +853,28 @@ impl Step for Cargo {
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.build.require_submodule("src/tools/cargo", None);
 
+        builder.std(self.build_compiler, self.target);
         builder.ensure(ToolBuild {
-            build_compiler: self.compiler,
+            build_compiler: self.build_compiler,
             target: self.target,
             tool: "cargo",
-            mode: Mode::ToolRustc,
+            mode: Mode::ToolTarget,
             path: "src/tools/cargo",
             source_type: SourceType::Submodule,
             extra_features: Vec::new(),
-            allow_features: "",
+            // Cargo is compilable with a stable compiler, but since we run in bootstrap,
+            // with RUSTC_BOOTSTRAP being set, some "clever" build scripts enable specialization
+            // based on this, which breaks stuff. We thus have to explicitly allow these features
+            // here.
+            allow_features: "min_specialization,specialization",
             cargo_args: Vec::new(),
             artifact_kind: ToolArtifactKind::Binary,
         })
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::build("cargo", self.target).built_by(self.build_compiler))
+    }
 }
 
 /// Represents a built LldWrapper, the `lld-wrapper` tool itself, and a directory
@@ -1066,8 +1055,13 @@ impl Step for WasmComponentLd {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RustAnalyzer {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    compilers: RustcPrivateCompilers,
+}
+
+impl RustAnalyzer {
+    pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
+        Self { compilers }
+    }
 }
 
 impl RustAnalyzer {
@@ -1086,15 +1080,16 @@ impl Step for RustAnalyzer {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RustAnalyzer {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
-            target: run.target,
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
+        let build_compiler = self.compilers.build_compiler;
+        let target = self.compilers.target();
         builder.ensure(ToolBuild {
-            build_compiler: self.compiler,
-            target: self.target,
+            build_compiler,
+            target,
             tool: "rust-analyzer",
             mode: Mode::ToolRustc,
             path: "src/tools/rust-analyzer",
@@ -1105,16 +1100,29 @@ impl Step for RustAnalyzer {
             artifact_kind: ToolArtifactKind::Binary,
         })
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::build("rust-analyzer", self.compilers.target())
+                .built_by(self.compilers.build_compiler),
+        )
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RustAnalyzerProcMacroSrv {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    compilers: RustcPrivateCompilers,
+}
+
+impl RustAnalyzerProcMacroSrv {
+    pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
+        Self { compilers }
+    }
 }
 
 impl Step for RustAnalyzerProcMacroSrv {
-    type Output = Option<ToolBuildResult>;
+    type Output = ToolBuildResult;
+
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -1131,15 +1139,14 @@ impl Step for RustAnalyzerProcMacroSrv {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RustAnalyzerProcMacroSrv {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
-            target: run.target,
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
         });
     }
 
-    fn run(self, builder: &Builder<'_>) -> Option<ToolBuildResult> {
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
         let tool_result = builder.ensure(ToolBuild {
-            build_compiler: self.compiler,
-            target: self.target,
+            build_compiler: self.compilers.build_compiler,
+            target: self.compilers.target(),
             tool: "rust-analyzer-proc-macro-srv",
             mode: Mode::ToolRustc,
             path: "src/tools/rust-analyzer/crates/proc-macro-srv-cli",
@@ -1152,7 +1159,7 @@ impl Step for RustAnalyzerProcMacroSrv {
 
         // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
         // so that r-a can use it.
-        let libexec_path = builder.sysroot(self.compiler).join("libexec");
+        let libexec_path = builder.sysroot(self.compilers.target_compiler).join("libexec");
         t!(fs::create_dir_all(&libexec_path));
         builder.copy_link(
             &tool_result.tool_path,
@@ -1160,7 +1167,14 @@ impl Step for RustAnalyzerProcMacroSrv {
             FileType::Executable,
         );
 
-        Some(tool_result)
+        tool_result
+    }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::build("rust-analyzer-proc-macro-srv", self.compilers.target())
+                .built_by(self.compilers.build_compiler),
+        )
     }
 }
 
@@ -1302,7 +1316,92 @@ impl Step for LibcxxVersionTool {
     }
 }
 
-macro_rules! tool_extended {
+/// Represents which compilers are involved in the compilation of a tool
+/// that depends on compiler internals (`rustc_private`).
+/// Their compilation looks like this:
+///
+/// - `build_compiler` (stage N-1) builds `target_compiler` (stage N) to produce .rlibs
+///     - These .rlibs are copied into the sysroot of `build_compiler`
+/// - `build_compiler` (stage N-1) builds `<tool>` (stage N)
+///     - `<tool>` links to .rlibs from `target_compiler`
+///
+/// Eventually, this could also be used for .rmetas and check builds, but so far we only deal with
+/// normal builds here.
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct RustcPrivateCompilers {
+    /// Compiler that builds the tool and that builds `target_compiler`.
+    build_compiler: Compiler,
+    /// Compiler to which .rlib artifacts the tool links to.
+    /// The host target of this compiler corresponds to the target of the tool.
+    target_compiler: Compiler,
+}
+
+impl RustcPrivateCompilers {
+    /// Create compilers for a `rustc_private` tool with the given `stage` and for the given
+    /// `target`.
+    pub fn new(builder: &Builder<'_>, stage: u32, target: TargetSelection) -> Self {
+        let build_compiler = Self::build_compiler_from_stage(builder, stage);
+
+        // This is the compiler we'll link to
+        // FIXME: make 100% sure that `target_compiler` was indeed built with `build_compiler`...
+        let target_compiler = builder.compiler(build_compiler.stage + 1, target);
+
+        Self { build_compiler, target_compiler }
+    }
+
+    pub fn from_build_and_target_compiler(
+        build_compiler: Compiler,
+        target_compiler: Compiler,
+    ) -> Self {
+        Self { build_compiler, target_compiler }
+    }
+
+    /// Create rustc tool compilers from the build compiler.
+    pub fn from_build_compiler(
+        builder: &Builder<'_>,
+        build_compiler: Compiler,
+        target: TargetSelection,
+    ) -> Self {
+        let target_compiler = builder.compiler(build_compiler.stage + 1, target);
+        Self { build_compiler, target_compiler }
+    }
+
+    /// Create rustc tool compilers from the target compiler.
+    pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+        Self {
+            build_compiler: Self::build_compiler_from_stage(builder, target_compiler.stage),
+            target_compiler,
+        }
+    }
+
+    fn build_compiler_from_stage(builder: &Builder<'_>, stage: u32) -> Compiler {
+        assert!(stage > 0);
+
+        if builder.download_rustc() && stage == 1 {
+            // We shouldn't drop to stage0 compiler when using CI rustc.
+            builder.compiler(1, builder.config.host_target)
+        } else {
+            builder.compiler(stage - 1, builder.config.host_target)
+        }
+    }
+
+    pub fn build_compiler(&self) -> Compiler {
+        self.build_compiler
+    }
+
+    pub fn target_compiler(&self) -> Compiler {
+        self.target_compiler
+    }
+
+    /// Target of the tool being compiled
+    pub fn target(&self) -> TargetSelection {
+        self.target_compiler.host
+    }
+}
+
+/// Creates a step that builds an extended `Mode::ToolRustc` tool
+/// and installs it into the sysroot of a corresponding compiler.
+macro_rules! tool_rustc_extended {
     (
         $name:ident {
             path: $path:expr,
@@ -1316,8 +1415,15 @@ macro_rules! tool_extended {
     ) => {
         #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         pub struct $name {
-            pub compiler: Compiler,
-            pub target: TargetSelection,
+            compilers: RustcPrivateCompilers,
+        }
+
+        impl $name {
+            pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
+                Self {
+                    compilers,
+                }
+            }
         }
 
         impl Step for $name {
@@ -1326,7 +1432,7 @@ macro_rules! tool_extended {
             const ONLY_HOSTS: bool = true;
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-                should_run_tool_build_step(
+                should_run_extended_rustc_tool(
                     run,
                     $tool_name,
                     $path,
@@ -1336,17 +1442,15 @@ macro_rules! tool_extended {
 
             fn make_run(run: RunConfig<'_>) {
                 run.builder.ensure($name {
-                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
-                    target: run.target,
+                    compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
                 });
             }
 
             fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
-                let Self { compiler, target } = self;
-                run_tool_build_step(
+                let Self { compilers } = self;
+                build_extended_rustc_tool(
                     builder,
-                    compiler,
-                    target,
+                    compilers,
                     $tool_name,
                     $path,
                     None $( .or(Some(&$add_bins_to_sysroot)) )?,
@@ -1356,18 +1460,16 @@ macro_rules! tool_extended {
             }
 
             fn metadata(&self) -> Option<StepMetadata> {
-                // FIXME: refactor extended tool steps to make the build_compiler explicit,
-                // it is offset by one now for rustc tools
                 Some(
-                    StepMetadata::build($tool_name, self.target)
-                        .built_by(self.compiler.with_stage(self.compiler.stage.saturating_sub(1)))
+                    StepMetadata::build($tool_name, self.compilers.target())
+                        .built_by(self.compilers.build_compiler)
                 )
             }
         }
     }
 }
 
-fn should_run_tool_build_step<'a>(
+fn should_run_extended_rustc_tool<'a>(
     run: ShouldRun<'a>,
     tool_name: &'static str,
     path: &'static str,
@@ -1391,39 +1493,38 @@ fn should_run_tool_build_step<'a>(
     )
 }
 
-#[expect(clippy::too_many_arguments)] // silence overeager clippy lint
-fn run_tool_build_step(
+fn build_extended_rustc_tool(
     builder: &Builder<'_>,
-    compiler: Compiler,
-    target: TargetSelection,
+    compilers: RustcPrivateCompilers,
     tool_name: &'static str,
     path: &'static str,
     add_bins_to_sysroot: Option<&[&str]>,
     add_features: Option<fn(&Builder<'_>, TargetSelection, &mut Vec<String>)>,
     cargo_args: Option<&[&'static str]>,
 ) -> ToolBuildResult {
+    let target = compilers.target();
     let mut extra_features = Vec::new();
     if let Some(func) = add_features {
         func(builder, target, &mut extra_features);
     }
 
-    let ToolBuildResult { tool_path, build_compiler, target_compiler } =
-        builder.ensure(ToolBuild {
-            build_compiler: compiler,
-            target,
-            tool: tool_name,
-            mode: Mode::ToolRustc,
-            path,
-            extra_features,
-            source_type: SourceType::InTree,
-            allow_features: "",
-            cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(),
-            artifact_kind: ToolArtifactKind::Binary,
-        });
-
+    let build_compiler = compilers.build_compiler;
+    let ToolBuildResult { tool_path, .. } = builder.ensure(ToolBuild {
+        build_compiler,
+        target,
+        tool: tool_name,
+        mode: Mode::ToolRustc,
+        path,
+        extra_features,
+        source_type: SourceType::InTree,
+        allow_features: "",
+        cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(),
+        artifact_kind: ToolArtifactKind::Binary,
+    });
+
+    let target_compiler = compilers.target_compiler;
     if let Some(add_bins_to_sysroot) = add_bins_to_sysroot
         && !add_bins_to_sysroot.is_empty()
-        && target_compiler.stage > 0
     {
         let bindir = builder.sysroot(target_compiler).join("bin");
         t!(fs::create_dir_all(&bindir));
@@ -1435,25 +1536,25 @@ fn run_tool_build_step(
 
         // Return a path into the bin dir.
         let path = bindir.join(exe(tool_name, target_compiler.host));
-        ToolBuildResult { tool_path: path, build_compiler, target_compiler }
+        ToolBuildResult { tool_path: path, build_compiler }
     } else {
-        ToolBuildResult { tool_path, build_compiler, target_compiler }
+        ToolBuildResult { tool_path, build_compiler }
     }
 }
 
-tool_extended!(Cargofmt {
+tool_rustc_extended!(Cargofmt {
     path: "src/tools/rustfmt",
     tool_name: "cargo-fmt",
     stable: true,
     add_bins_to_sysroot: ["cargo-fmt"]
 });
-tool_extended!(CargoClippy {
+tool_rustc_extended!(CargoClippy {
     path: "src/tools/clippy",
     tool_name: "cargo-clippy",
     stable: true,
     add_bins_to_sysroot: ["cargo-clippy"]
 });
-tool_extended!(Clippy {
+tool_rustc_extended!(Clippy {
     path: "src/tools/clippy",
     tool_name: "clippy-driver",
     stable: true,
@@ -1464,7 +1565,7 @@ tool_extended!(Clippy {
         }
     }
 });
-tool_extended!(Miri {
+tool_rustc_extended!(Miri {
     path: "src/tools/miri",
     tool_name: "miri",
     stable: false,
@@ -1472,13 +1573,13 @@ tool_extended!(Miri {
     // Always compile also tests when building miri. Otherwise feature unification can cause rebuilds between building and testing miri.
     cargo_args: &["--all-targets"],
 });
-tool_extended!(CargoMiri {
+tool_rustc_extended!(CargoMiri {
     path: "src/tools/miri/cargo-miri",
     tool_name: "cargo-miri",
     stable: false,
     add_bins_to_sysroot: ["cargo-miri"]
 });
-tool_extended!(Rustfmt {
+tool_rustc_extended!(Rustfmt {
     path: "src/tools/rustfmt",
     tool_name: "rustfmt",
     stable: true,
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 6b3236ef47e..e10af2b55f9 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -115,7 +115,7 @@ impl Cargo {
             // No need to configure the target linker for these command types.
             Kind::Clean | Kind::Check | Kind::Format | Kind::Setup => {}
             _ => {
-                cargo.configure_linker(builder, mode);
+                cargo.configure_linker(builder);
             }
         }
 
@@ -209,7 +209,7 @@ impl Cargo {
 
     // FIXME(onur-ozkan): Add coverage to make sure modifications to this function
     // doesn't cause cache invalidations (e.g., #130108).
-    fn configure_linker(&mut self, builder: &Builder<'_>, mode: Mode) -> &mut Cargo {
+    fn configure_linker(&mut self, builder: &Builder<'_>) -> &mut Cargo {
         let target = self.target;
         let compiler = self.compiler;
 
@@ -264,12 +264,7 @@ impl Cargo {
             }
         }
 
-        // We use the snapshot compiler when building host code (build scripts/proc macros) of
-        // `Mode::Std` tools, so we need to determine the current stage here to pass the proper
-        // linker args (e.g. -C vs -Z).
-        // This should stay synchronized with the [cargo] function.
-        let host_stage = if mode == Mode::Std { 0 } else { compiler.stage };
-        for arg in linker_args(builder, compiler.host, LldThreads::Yes, host_stage) {
+        for arg in linker_args(builder, compiler.host, LldThreads::Yes) {
             self.hostflags.arg(&arg);
         }
 
@@ -279,10 +274,10 @@ impl Cargo {
         }
         // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
         // `linker_args` here.
-        for flag in linker_flags(builder, target, LldThreads::Yes, compiler.stage) {
+        for flag in linker_flags(builder, target, LldThreads::Yes) {
             self.rustflags.arg(&flag);
         }
-        for arg in linker_args(builder, target, LldThreads::Yes, compiler.stage) {
+        for arg in linker_args(builder, target, LldThreads::Yes) {
             self.rustdocflags.arg(&arg);
         }
 
@@ -508,7 +503,7 @@ impl Builder<'_> {
                 }
                 _ => panic!("doc mode {mode:?} not expected"),
             };
-            let rustdoc = self.rustdoc(compiler);
+            let rustdoc = self.rustdoc_for_compiler(compiler);
             build_stamp::clear_if_dirty(self, &my_out, &rustdoc);
         }
 
@@ -822,7 +817,7 @@ impl Builder<'_> {
         }
 
         let rustdoc_path = match cmd_kind {
-            Kind::Doc | Kind::Test | Kind::MiriTest => self.rustdoc(compiler),
+            Kind::Doc | Kind::Test | Kind::MiriTest => self.rustdoc_for_compiler(compiler),
             _ => PathBuf::from("/path/to/nowhere/rustdoc/not/required"),
         };
 
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 20f3fee1c6c..e15941938f1 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -16,6 +16,7 @@ use tracing::instrument;
 pub use self::cargo::{Cargo, cargo_profile_var};
 pub use crate::Compiler;
 use crate::core::build_steps::compile::{Std, StdLink};
+use crate::core::build_steps::tool::RustcPrivateCompilers;
 use crate::core::build_steps::{
     check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, tool, vendor,
 };
@@ -1543,8 +1544,11 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
             .map(|entry| entry.path())
     }
 
-    pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
-        self.ensure(tool::Rustdoc { compiler }).tool_path
+    /// Returns a path to `Rustdoc` that "belongs" to the `target_compiler`.
+    /// It can be either a stage0 rustdoc or a locally built rustdoc that *links* to
+    /// `target_compiler`.
+    pub fn rustdoc_for_compiler(&self, target_compiler: Compiler) -> PathBuf {
+        self.ensure(tool::Rustdoc { target_compiler })
     }
 
     pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand {
@@ -1560,10 +1564,13 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
             return cmd;
         }
 
-        let _ =
-            self.ensure(tool::Clippy { compiler: run_compiler, target: self.build.host_target });
-        let cargo_clippy = self
-            .ensure(tool::CargoClippy { compiler: run_compiler, target: self.build.host_target });
+        // FIXME: double check that `run_compiler`'s stage is what we want to use
+        let compilers =
+            RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target);
+        assert_eq!(run_compiler, compilers.target_compiler());
+
+        let _ = self.ensure(tool::Clippy::from_compilers(compilers));
+        let cargo_clippy = self.ensure(tool::CargoClippy::from_compilers(compilers));
         let mut dylib_path = helpers::dylib_path();
         dylib_path.insert(0, self.sysroot(run_compiler).join("lib"));
 
@@ -1575,11 +1582,14 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
 
     pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand {
         assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0");
+
+        let compilers =
+            RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target);
+        assert_eq!(run_compiler, compilers.target_compiler());
+
         // Prepare the tools
-        let miri =
-            self.ensure(tool::Miri { compiler: run_compiler, target: self.build.host_target });
-        let cargo_miri =
-            self.ensure(tool::CargoMiri { compiler: run_compiler, target: self.build.host_target });
+        let miri = self.ensure(tool::Miri::from_compilers(compilers));
+        let cargo_miri = self.ensure(tool::CargoMiri::from_compilers(compilers));
         // Invoke cargo-miri, make sure it can find miri and cargo.
         let mut cmd = command(cargo_miri.tool_path);
         cmd.env("MIRI", &miri.tool_path);
@@ -1604,7 +1614,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
             // equivalently to rustc.
             .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
             .env("CFG_RELEASE_CHANNEL", &self.config.channel)
-            .env("RUSTDOC_REAL", self.rustdoc(compiler))
+            .env("RUSTDOC_REAL", self.rustdoc_for_compiler(compiler))
             .env("RUSTC_BOOTSTRAP", "1");
 
         cmd.arg("-Wrustdoc::invalid_codeblock_attributes");
@@ -1613,7 +1623,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
             cmd.arg("-Dwarnings");
         }
         cmd.arg("-Znormalize-docs");
-        cmd.args(linker_args(self, compiler.host, LldThreads::Yes, compiler.stage));
+        cmd.args(linker_args(self, compiler.host, LldThreads::Yes));
         cmd
     }
 
@@ -1728,11 +1738,11 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
     /// Ensure that a given step is built *only if it's supposed to be built by default*, returning
     /// its output. This will cache the step, so it's safe (and good!) to call this as often as
     /// needed to ensure that all dependencies are build.
-    pub(crate) fn ensure_if_default<T, S: Step<Output = Option<T>>>(
+    pub(crate) fn ensure_if_default<T, S: Step<Output = T>>(
         &'a self,
         step: S,
         kind: Kind,
-    ) -> S::Output {
+    ) -> Option<S::Output> {
         let desc = StepDescription::from::<S>(kind);
         let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
 
@@ -1744,7 +1754,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
         }
 
         // Only execute if it's supposed to run as default
-        if desc.default && should_run.is_really_default() { self.ensure(step) } else { None }
+        if desc.default && should_run.is_really_default() { Some(self.ensure(step)) } else { None }
     }
 
     /// Checks if any of the "should_run" paths is in the `Builder` paths.
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index f012645b7ef..5361347da90 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -257,38 +257,6 @@ fn parse_config_download_rustc_at(path: &Path, download_rustc: &str, ci: bool) -
     )
 }
 
-mod defaults {
-    use pretty_assertions::assert_eq;
-
-    use super::{TEST_TRIPLE_1, TEST_TRIPLE_2, configure, first, run_build};
-    use crate::Config;
-    use crate::core::builder::*;
-
-    #[test]
-    fn doc_default() {
-        let mut config = configure("doc", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
-        config.compiler_docs = true;
-        config.cmd = Subcommand::Doc { open: false, json: false };
-        let mut cache = run_build(&[], config);
-        let a = TargetSelection::from_user(TEST_TRIPLE_1);
-
-        // error_index_generator uses stage 0 to share rustdoc artifacts with the
-        // rustdoc tool.
-        assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
-        assert_eq!(
-            first(cache.all::<tool::ErrorIndex>()),
-            &[tool::ErrorIndex { compiler: Compiler::new(1, a) }]
-        );
-        // docs should be built with the stage0 compiler, not with the stage0 artifacts.
-        // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
-        // not the one it was built by.
-        assert_eq!(
-            first(cache.all::<tool::Rustdoc>()),
-            &[tool::Rustdoc { compiler: Compiler::new(1, a) },]
-        );
-    }
-}
-
 mod dist {
     use pretty_assertions::assert_eq;
 
@@ -316,34 +284,6 @@ mod dist {
         let target = TargetSelection::from_user(TEST_TRIPLE_1);
         assert!(build.llvm_out(target).ends_with("llvm"));
     }
-
-    #[test]
-    fn doc_ci() {
-        let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
-        config.compiler_docs = true;
-        config.cmd = Subcommand::Doc { open: false, json: false };
-        let build = Build::new(config);
-        let mut builder = Builder::new(&build);
-        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
-        let a = TargetSelection::from_user(TEST_TRIPLE_1);
-
-        // error_index_generator uses stage 1 to share rustdoc artifacts with the
-        // rustdoc tool.
-        assert_eq!(
-            first(builder.cache.all::<doc::ErrorIndex>()),
-            &[doc::ErrorIndex { target: a },]
-        );
-        assert_eq!(
-            first(builder.cache.all::<tool::ErrorIndex>()),
-            &[tool::ErrorIndex { compiler: Compiler::new(1, a) }]
-        );
-        // This is actually stage 1, but Rustdoc::run swaps out the compiler with
-        // stage minus 1 if --stage is not 0. Very confusing!
-        assert_eq!(
-            first(builder.cache.all::<tool::Rustdoc>()),
-            &[tool::Rustdoc { compiler: Compiler::new(2, a) },]
-        );
-    }
 }
 
 mod sysroot_target_dirs {
@@ -569,36 +509,6 @@ fn test_is_builder_target() {
     }
 }
 
-#[test]
-fn test_get_tool_rustc_compiler() {
-    let mut config = configure("build", &[], &[]);
-    config.download_rustc_commit = None;
-    let build = Build::new(config);
-    let builder = Builder::new(&build);
-
-    let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
-
-    let compiler = Compiler::new(2, target_triple_1);
-    let expected = Compiler::new(1, target_triple_1);
-    let actual = tool::get_tool_rustc_compiler(&builder, compiler);
-    assert_eq!(expected, actual);
-
-    let compiler = Compiler::new(1, target_triple_1);
-    let expected = Compiler::new(0, target_triple_1);
-    let actual = tool::get_tool_rustc_compiler(&builder, compiler);
-    assert_eq!(expected, actual);
-
-    let mut config = configure("build", &[], &[]);
-    config.download_rustc_commit = Some("".to_owned());
-    let build = Build::new(config);
-    let builder = Builder::new(&build);
-
-    let compiler = Compiler::new(1, target_triple_1);
-    let expected = Compiler::new(1, target_triple_1);
-    let actual = tool::get_tool_rustc_compiler(&builder, compiler);
-    assert_eq!(expected, actual);
-}
-
 /// When bootstrap detects a step dependency cycle (which is a bug), its panic
 /// message should show the actual steps on the stack, not just several copies
 /// of `Any { .. }`.
@@ -657,7 +567,7 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         ");
     }
 
@@ -680,10 +590,10 @@ mod snapshot {
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [build] llvm <target1>
         [build] rustc 1 <host> -> rustc 2 <target1>
-        [build] rustdoc 1 <target1>
+        [build] rustdoc 2 <target1>
         ");
     }
 
@@ -763,6 +673,23 @@ mod snapshot {
     }
 
     #[test]
+    fn build_compiler_codegen_backend() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx
+                .config("build")
+                .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"])
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> rustc_codegen_cranelift 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustdoc 1 <host>
+        "
+        );
+    }
+
+    #[test]
     fn build_compiler_tools() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
@@ -780,7 +707,7 @@ mod snapshot {
         [build] rustc 1 <host> -> LldWrapper 2 <host>
         [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
         [build] rustc 2 <host> -> std 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         "
         );
     }
@@ -809,7 +736,7 @@ mod snapshot {
         [build] rustc 1 <host> -> rustc 2 <target1>
         [build] rustc 1 <host> -> LldWrapper 2 <target1>
         [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
-        [build] rustdoc 1 <target1>
+        [build] rustdoc 2 <target1>
         "
         );
     }
@@ -915,6 +842,19 @@ mod snapshot {
     }
 
     #[test]
+    fn build_error_index() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("build")
+                .path("error_index_generator")
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> error-index 1 <host>
+        ");
+    }
+
+    #[test]
     fn build_bootstrap_tool_no_explicit_stage() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
@@ -998,7 +938,7 @@ mod snapshot {
             .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
         ");
     }
@@ -1027,6 +967,15 @@ mod snapshot {
     }
 
     #[test]
+    fn build_cargo() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("build")
+                .paths(&["cargo"])
+            .render_steps(), @"[build] rustc 0 <host> -> cargo 1 <host>");
+    }
+
+    #[test]
     fn dist_default_stage() {
         let ctx = TestCtx::new();
         assert_eq!(ctx.config("dist").path("compiler").create_config().stage, 2);
@@ -1047,8 +996,10 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
@@ -1089,24 +1040,29 @@ mod snapshot {
         [build] rustc 1 <host> -> LldWrapper 2 <host>
         [build] rustc 1 <host> -> WasmComponentLd 2 <host>
         [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
         [doc] std 2 <host> crates=[]
         [dist] mingw <host>
+        [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
         [dist] rustc 1 <host> -> std 1 <host>
         [dist] src <>
-        [build] rustc 0 <host> -> rustfmt 1 <host>
-        [build] rustc 0 <host> -> cargo-fmt 1 <host>
-        [build] rustc 0 <host> -> clippy-driver 1 <host>
-        [build] rustc 0 <host> -> cargo-clippy 1 <host>
-        [build] rustc 0 <host> -> miri 1 <host>
-        [build] rustc 0 <host> -> cargo-miri 1 <host>
+        [build] rustc 1 <host> -> cargo 2 <host>
+        [build] rustc 1 <host> -> rust-analyzer 2 <host>
+        [build] rustc 1 <host> -> rustfmt 2 <host>
+        [build] rustc 1 <host> -> cargo-fmt 2 <host>
+        [build] rustc 1 <host> -> clippy-driver 2 <host>
+        [build] rustc 1 <host> -> cargo-clippy 2 <host>
+        [build] rustc 1 <host> -> miri 2 <host>
+        [build] rustc 1 <host> -> cargo-miri 2 <host>
         ");
     }
 
@@ -1125,9 +1081,11 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
         [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
@@ -1162,11 +1120,17 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
+        [build] llvm <target1>
+        [build] rustc 1 <host> -> std 1 <target1>
+        [build] rustc 1 <host> -> rustc 2 <target1>
+        [build] rustc 1 <host> -> error-index 2 <target1>
+        [doc] rustc 1 <host> -> error-index 2 <target1>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
-        [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
@@ -1174,9 +1138,7 @@ mod snapshot {
         [dist] mingw <host>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
-        [build] llvm <target1>
-        [build] rustc 1 <host> -> rustc 2 <target1>
-        [build] rustdoc 1 <target1>
+        [build] rustdoc 2 <target1>
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <host>
         [dist] src <>
@@ -1199,12 +1161,18 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
         [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
+        [build] llvm <target1>
+        [build] rustc 1 <host> -> std 1 <target1>
+        [build] rustc 1 <host> -> rustc 2 <target1>
+        [build] rustc 1 <host> -> error-index 2 <target1>
+        [doc] rustc 1 <host> -> error-index 2 <target1>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
-        [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
@@ -1215,9 +1183,7 @@ mod snapshot {
         [dist] mingw <target1>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
-        [build] llvm <target1>
-        [build] rustc 1 <host> -> rustc 2 <target1>
-        [build] rustdoc 1 <target1>
+        [build] rustdoc 2 <target1>
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <host>
         [dist] rustc 1 <host> -> std 1 <target1>
@@ -1241,7 +1207,7 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
@@ -1273,30 +1239,35 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustc 1 <host> -> WasmComponentLd 2 <host>
-        [build] rustdoc 1 <host>
+        [build] rustdoc 2 <host>
         [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
-        [build] rustc 2 <host> -> std 2 <host>
+        [build] llvm <target1>
         [build] rustc 1 <host> -> std 1 <target1>
+        [build] rustc 1 <host> -> rustc 2 <target1>
+        [build] rustc 1 <host> -> WasmComponentLd 2 <target1>
+        [build] rustc 1 <host> -> error-index 2 <target1>
+        [doc] rustc 1 <host> -> error-index 2 <target1>
+        [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <target1>
         [doc] std 2 <target1> crates=[]
         [dist] mingw <target1>
-        [build] llvm <target1>
-        [build] rustc 1 <host> -> rustc 2 <target1>
-        [build] rustc 1 <host> -> WasmComponentLd 2 <target1>
-        [build] rustdoc 1 <target1>
+        [build] rustdoc 2 <target1>
+        [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <target1>
         [dist] src <>
-        [build] rustc 0 <host> -> rustfmt 1 <target1>
-        [build] rustc 0 <host> -> cargo-fmt 1 <target1>
-        [build] rustc 0 <host> -> clippy-driver 1 <target1>
-        [build] rustc 0 <host> -> cargo-clippy 1 <target1>
-        [build] rustc 0 <host> -> miri 1 <target1>
-        [build] rustc 0 <host> -> cargo-miri 1 <target1>
+        [build] rustc 1 <host> -> cargo 2 <target1>
+        [build] rustc 1 <host> -> rust-analyzer 2 <target1>
+        [build] rustc 1 <host> -> rustfmt 2 <target1>
+        [build] rustc 1 <host> -> cargo-fmt 2 <target1>
+        [build] rustc 1 <host> -> clippy-driver 2 <target1>
+        [build] rustc 1 <host> -> cargo-clippy 2 <target1>
+        [build] rustc 1 <host> -> miri 2 <target1>
+        [build] rustc 1 <host> -> cargo-miri 2 <target1>
         [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
         ");
     }
@@ -1611,6 +1582,77 @@ mod snapshot {
     }
 
     #[test]
+    fn test_cargo_stage_1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("test")
+                .path("cargo")
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> cargo 1 <host>
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustdoc 1 <host>
+        [build] rustdoc 0 <host>
+        ");
+    }
+
+    #[test]
+    fn test_cargo_stage_2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("test")
+                .path("cargo")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> cargo 2 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 2 <host> -> std 2 <host>
+        [build] rustdoc 2 <host>
+        [build] rustdoc 1 <host>
+        ");
+    }
+
+    #[test]
+    fn test_cargotest() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("test")
+                .path("cargotest")
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> cargo 1 <host>
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 0 <host> -> CargoTest 1 <host>
+        [build] rustdoc 1 <host>
+        [test] cargotest 1 <host>
+        ");
+    }
+
+    #[test]
+    fn doc_all() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> UnstableBookGen 1 <host>
+        [build] rustc 0 <host> -> Rustbook 1 <host>
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 1 <host>
+        [doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 0 <host> -> error-index 1 <host>
+        [doc] rustc 0 <host> -> error-index 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 0 <host> -> LintDocs 1 <host>
+        ");
+    }
+
+    #[test]
     fn doc_library() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
@@ -1619,7 +1661,7 @@ mod snapshot {
                 .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
         ");
     }
@@ -1633,7 +1675,7 @@ mod snapshot {
                 .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <host> crates=[core]
         ");
     }
@@ -1648,7 +1690,7 @@ mod snapshot {
                 .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <host> crates=[core]
         ");
     }
@@ -1678,7 +1720,7 @@ mod snapshot {
                 .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <host> crates=[alloc,core]
         ");
     }
@@ -1694,10 +1736,105 @@ mod snapshot {
                 .render_steps(), @r"
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
-        [build] rustdoc 0 <host>
+        [build] rustdoc 1 <host>
         [doc] std 1 <target1> crates=[alloc,core]
         ");
     }
+
+    #[test]
+    fn doc_compiler_stage_0() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("compiler")
+                .stage(0)
+                .render_steps(), @r"
+        [build] rustdoc 0 <host>
+        [build] llvm <host>
+        [doc] rustc 0 <host>
+        ");
+    }
+
+    #[test]
+    fn doc_compiler_stage_1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("compiler")
+                .stage(1)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustdoc 1 <host>
+        [doc] rustc 1 <host>
+        ");
+    }
+
+    #[test]
+    fn doc_compiler_stage_2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("compiler")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 2 <host> -> std 2 <host>
+        [build] rustdoc 2 <host>
+        [doc] rustc 2 <host>
+        ");
+    }
+
+    #[test]
+    fn doc_compiletest_stage_0() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("src/tools/compiletest")
+                .stage(0)
+                .render_steps(), @r"
+        [build] rustdoc 0 <host>
+        [doc] Compiletest <host>
+        ");
+    }
+
+    #[test]
+    fn doc_compiletest_stage_1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("src/tools/compiletest")
+                .stage(1)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustdoc 1 <host>
+        [doc] Compiletest <host>
+        ");
+    }
+
+    #[test]
+    fn doc_compiletest_stage_2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("src/tools/compiletest")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 2 <host> -> std 2 <host>
+        [build] rustdoc 2 <host>
+        [doc] Compiletest <host>
+        ");
+    }
 }
 
 struct ExecutedSteps {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 6055876c475..2c008f957d9 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -32,13 +32,18 @@ use tracing::{instrument, span};
 use crate::core::build_steps::llvm;
 use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
 pub use crate::core::config::flags::Subcommand;
-use crate::core::config::flags::{Color, Flags};
+use crate::core::config::flags::{Color, Flags, Warnings};
 use crate::core::config::target_selection::TargetSelectionList;
 use crate::core::config::toml::TomlConfig;
 use crate::core::config::toml::build::{Build, Tool};
 use crate::core::config::toml::change_id::ChangeId;
+use crate::core::config::toml::dist::Dist;
+use crate::core::config::toml::gcc::Gcc;
+use crate::core::config::toml::install::Install;
+use crate::core::config::toml::llvm::Llvm;
 use crate::core::config::toml::rust::{
-    LldMode, RustOptimize, check_incompatible_options_for_ci_rustc,
+    LldMode, Rust, RustOptimize, check_incompatible_options_for_ci_rustc,
+    default_lld_opt_in_targets, parse_codegen_backends,
 };
 use crate::core::config::toml::target::Target;
 use crate::core::config::{
@@ -89,7 +94,6 @@ pub struct Config {
     pub ccache: Option<String>,
     /// Call Build::ninja() instead of this.
     pub ninja_in_file: bool,
-    pub verbose: usize,
     pub submodules: Option<bool>,
     pub compiler_docs: bool,
     pub library_docs_private_items: bool,
@@ -442,23 +446,13 @@ impl Config {
             enable_bolt_settings: flags_enable_bolt_settings,
             skip_stage0_validation: flags_skip_stage0_validation,
             reproducible_artifact: flags_reproducible_artifact,
-            paths: mut flags_paths,
+            paths: flags_paths,
             set: flags_set,
-            free_args: mut flags_free_args,
+            free_args: flags_free_args,
             ci: flags_ci,
             skip_std_check_if_no_download_rustc: flags_skip_std_check_if_no_download_rustc,
         } = flags;
 
-        let mut config = Config::default_opts();
-        let mut exec_ctx = ExecutionContext::new();
-        exec_ctx.set_verbose(flags_verbose);
-        exec_ctx.set_fail_fast(flags_cmd.fail_fast());
-
-        config.exec_ctx = exec_ctx;
-
-        // Set flags.
-        config.paths = std::mem::take(&mut flags_paths);
-
         #[cfg(feature = "tracing")]
         span!(
             target: "CONFIG_HANDLING",
@@ -469,14 +463,251 @@ impl Config {
             "flags.exclude" = ?flags_exclude
         );
 
-        #[cfg(feature = "tracing")]
-        span!(
-            target: "CONFIG_HANDLING",
-            tracing::Level::TRACE,
-            "normalizing and combining `flag.skip`/`flag.exclude` paths",
-            "config.skip" = ?config.skip,
+        // First initialize the bare minimum that we need for further operation - source directory
+        // and execution context.
+        let mut config = Config::default_opts();
+        let exec_ctx = ExecutionContext::new(flags_verbose, flags_cmd.fail_fast());
+
+        config.exec_ctx = exec_ctx;
+
+        if let Some(src) = compute_src_directory(flags_src, &config.exec_ctx) {
+            config.src = src;
+        }
+
+        // Now load the TOML config, as soon as possible
+        let (mut toml, toml_path) = load_toml_config(&config.src, flags_config, &get_toml);
+        config.config = toml_path.clone();
+
+        postprocess_toml(
+            &mut toml,
+            &config.src,
+            toml_path,
+            config.exec_ctx(),
+            &flags_set,
+            &get_toml,
         );
 
+        // Now override TOML values with flags, to make sure that we won't later override flags with
+        // TOML values by accident instead, because flags have higher priority.
+        let Build {
+            description: build_description,
+            build: mut build_build,
+            host: build_host,
+            target: build_target,
+            build_dir: build_build_dir,
+            cargo: mut build_cargo,
+            rustc: mut build_rustc,
+            rustfmt: build_rustfmt,
+            cargo_clippy: build_cargo_clippy,
+            docs: build_docs,
+            compiler_docs: build_compiler_docs,
+            library_docs_private_items: build_library_docs_private_items,
+            docs_minification: build_docs_minification,
+            submodules: build_submodules,
+            gdb: build_gdb,
+            lldb: build_lldb,
+            nodejs: build_nodejs,
+            npm: build_npm,
+            python: build_python,
+            reuse: build_reuse,
+            locked_deps: build_locked_deps,
+            vendor: build_vendor,
+            full_bootstrap: build_full_bootstrap,
+            bootstrap_cache_path: build_bootstrap_cache_path,
+            extended: build_extended,
+            tools: build_tools,
+            tool: build_tool,
+            verbose: build_verbose,
+            sanitizers: build_sanitizers,
+            profiler: build_profiler,
+            cargo_native_static: build_cargo_native_static,
+            low_priority: build_low_priority,
+            configure_args: build_configure_args,
+            local_rebuild: build_local_rebuild,
+            print_step_timings: build_print_step_timings,
+            print_step_rusage: build_print_step_rusage,
+            check_stage: build_check_stage,
+            doc_stage: build_doc_stage,
+            build_stage: build_build_stage,
+            test_stage: build_test_stage,
+            install_stage: build_install_stage,
+            dist_stage: build_dist_stage,
+            bench_stage: build_bench_stage,
+            patch_binaries_for_nix: build_patch_binaries_for_nix,
+            // This field is only used by bootstrap.py
+            metrics: _,
+            android_ndk: build_android_ndk,
+            optimized_compiler_builtins: build_optimized_compiler_builtins,
+            jobs: mut build_jobs,
+            compiletest_diff_tool: build_compiletest_diff_tool,
+            compiletest_use_stage0_libtest: build_compiletest_use_stage0_libtest,
+            tidy_extra_checks: build_tidy_extra_checks,
+            ccache: build_ccache,
+            exclude: build_exclude,
+            compiletest_allow_stage0: build_compiletest_allow_stage0,
+        } = toml.build.unwrap_or_default();
+
+        let Install {
+            prefix: install_prefix,
+            sysconfdir: install_sysconfdir,
+            docdir: install_docdir,
+            bindir: install_bindir,
+            libdir: install_libdir,
+            mandir: install_mandir,
+            datadir: install_datadir,
+        } = toml.install.unwrap_or_default();
+
+        let Rust {
+            optimize: rust_optimize,
+            debug: rust_debug,
+            codegen_units: rust_codegen_units,
+            codegen_units_std: rust_codegen_units_std,
+            rustc_debug_assertions: rust_rustc_debug_assertions,
+            std_debug_assertions: rust_std_debug_assertions,
+            tools_debug_assertions: rust_tools_debug_assertions,
+            overflow_checks: rust_overflow_checks,
+            overflow_checks_std: rust_overflow_checks_std,
+            debug_logging: rust_debug_logging,
+            debuginfo_level: rust_debuginfo_level,
+            debuginfo_level_rustc: rust_debuginfo_level_rustc,
+            debuginfo_level_std: rust_debuginfo_level_std,
+            debuginfo_level_tools: rust_debuginfo_level_tools,
+            debuginfo_level_tests: rust_debuginfo_level_tests,
+            backtrace: rust_backtrace,
+            incremental: rust_incremental,
+            randomize_layout: rust_randomize_layout,
+            default_linker: rust_default_linker,
+            channel: rust_channel,
+            musl_root: rust_musl_root,
+            rpath: rust_rpath,
+            verbose_tests: rust_verbose_tests,
+            optimize_tests: rust_optimize_tests,
+            codegen_tests: rust_codegen_tests,
+            omit_git_hash: rust_omit_git_hash,
+            dist_src: rust_dist_src,
+            save_toolstates: rust_save_toolstates,
+            codegen_backends: rust_codegen_backends,
+            lld: rust_lld_enabled,
+            llvm_tools: rust_llvm_tools,
+            llvm_bitcode_linker: rust_llvm_bitcode_linker,
+            deny_warnings: rust_deny_warnings,
+            backtrace_on_ice: rust_backtrace_on_ice,
+            verify_llvm_ir: rust_verify_llvm_ir,
+            thin_lto_import_instr_limit: rust_thin_lto_import_instr_limit,
+            remap_debuginfo: rust_remap_debuginfo,
+            jemalloc: rust_jemalloc,
+            test_compare_mode: rust_test_compare_mode,
+            llvm_libunwind: rust_llvm_libunwind,
+            control_flow_guard: rust_control_flow_guard,
+            ehcont_guard: rust_ehcont_guard,
+            new_symbol_mangling: rust_new_symbol_mangling,
+            profile_generate: rust_profile_generate,
+            profile_use: rust_profile_use,
+            download_rustc: rust_download_rustc,
+            lto: rust_lto,
+            validate_mir_opts: rust_validate_mir_opts,
+            frame_pointers: rust_frame_pointers,
+            stack_protector: rust_stack_protector,
+            strip: rust_strip,
+            lld_mode: rust_lld_mode,
+            std_features: rust_std_features,
+        } = toml.rust.unwrap_or_default();
+
+        let Llvm {
+            optimize: llvm_optimize,
+            thin_lto: llvm_thin_lto,
+            release_debuginfo: llvm_release_debuginfo,
+            assertions: llvm_assertions,
+            tests: llvm_tests,
+            enzyme: llvm_enzyme,
+            plugins: llvm_plugin,
+            static_libstdcpp: llvm_static_libstdcpp,
+            libzstd: llvm_libzstd,
+            ninja: llvm_ninja,
+            targets: llvm_targets,
+            experimental_targets: llvm_experimental_targets,
+            link_jobs: llvm_link_jobs,
+            link_shared: llvm_link_shared,
+            version_suffix: llvm_version_suffix,
+            clang_cl: llvm_clang_cl,
+            cflags: llvm_cflags,
+            cxxflags: llvm_cxxflags,
+            ldflags: llvm_ldflags,
+            use_libcxx: llvm_use_libcxx,
+            use_linker: llvm_use_linker,
+            allow_old_toolchain: llvm_allow_old_toolchain,
+            offload: llvm_offload,
+            polly: llvm_polly,
+            clang: llvm_clang,
+            enable_warnings: llvm_enable_warnings,
+            download_ci_llvm: llvm_download_ci_llvm,
+            build_config: llvm_build_config,
+        } = toml.llvm.unwrap_or_default();
+
+        let Dist {
+            sign_folder: dist_sign_folder,
+            upload_addr: dist_upload_addr,
+            src_tarball: dist_src_tarball,
+            compression_formats: dist_compression_formats,
+            compression_profile: dist_compression_profile,
+            include_mingw_linker: dist_include_mingw_linker,
+            vendor: dist_vendor,
+        } = toml.dist.unwrap_or_default();
+
+        let Gcc { download_ci_gcc: gcc_download_ci_gcc } = toml.gcc.unwrap_or_default();
+
+        if cfg!(test) {
+            // When configuring bootstrap for tests, make sure to set the rustc and Cargo to the
+            // same ones used to call the tests (if custom ones are not defined in the toml). If we
+            // don't do that, bootstrap will use its own detection logic to find a suitable rustc
+            // and Cargo, which doesn't work when the caller is specìfying a custom local rustc or
+            // Cargo in their bootstrap.toml.
+            build_rustc = build_rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into()));
+            build_cargo = build_cargo.take().or(std::env::var_os("CARGO").map(|p| p.into()));
+        }
+
+        build_jobs = flags_jobs.or(build_jobs);
+        build_build = flags_build.or(build_build);
+
+        let build_dir = flags_build_dir.or(build_build_dir.map(PathBuf::from));
+        let host = if let Some(TargetSelectionList(hosts)) = flags_host {
+            Some(hosts)
+        } else {
+            build_host
+                .map(|file_host| file_host.iter().map(|h| TargetSelection::from_user(h)).collect())
+        };
+        let target = if let Some(TargetSelectionList(targets)) = flags_target {
+            Some(targets)
+        } else {
+            build_target.map(|file_target| {
+                file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
+            })
+        };
+
+        if let Some(rustc) = &build_rustc
+            && !flags_skip_stage0_validation
+        {
+            check_stage0_version(rustc, "rustc", &config.src, config.exec_ctx());
+        }
+        if let Some(cargo) = &build_cargo
+            && !flags_skip_stage0_validation
+        {
+            check_stage0_version(cargo, "cargo", &config.src, config.exec_ctx());
+        }
+
+        // Prefer CLI verbosity flags if set (`flags_verbose` > 0), otherwise take the value from
+        // TOML.
+        config
+            .exec_ctx
+            .set_verbosity(cmp::max(build_verbose.unwrap_or_default() as u8, flags_verbose));
+
+        let mut paths: Vec<PathBuf> = flags_skip.into_iter().chain(flags_exclude).collect();
+        if let Some(exclude) = build_exclude {
+            paths.extend(exclude);
+        }
+
+        // Set config values based on flags.
+        config.paths = flags_paths;
         config.include_default_paths = flags_include_default_paths;
         config.rustc_error_format = flags_rustc_error_format;
         config.json_output = flags_json_output;
@@ -489,7 +720,7 @@ impl Config {
         config.keep_stage = flags_keep_stage;
         config.keep_stage_std = flags_keep_stage_std;
         config.color = flags_color;
-        config.free_args = std::mem::take(&mut flags_free_args);
+        config.free_args = flags_free_args;
         config.llvm_profile_use = flags_llvm_profile_use;
         config.llvm_profile_generate = flags_llvm_profile_generate;
         config.enable_bolt_settings = flags_enable_bolt_settings;
@@ -499,53 +730,6 @@ impl Config {
 
         // Infer the rest of the configuration.
 
-        if let Some(src) = flags_src {
-            config.src = src
-        } else {
-            // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
-            // running on a completely different machine from where it was compiled.
-            let mut cmd = helpers::git(None);
-            // NOTE: we cannot support running from outside the repository because the only other path we have available
-            // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.
-            // We still support running outside the repository if we find we aren't in a git directory.
-
-            // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,
-            // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap
-            // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
-            cmd.arg("rev-parse").arg("--show-cdup");
-            // Discard stderr because we expect this to fail when building from a tarball.
-            let output = cmd.allow_failure().run_capture_stdout(&config);
-            if output.is_success() {
-                let git_root_relative = output.stdout();
-                // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
-                // and to resolve any relative components.
-                let git_root = env::current_dir()
-                    .unwrap()
-                    .join(PathBuf::from(git_root_relative.trim()))
-                    .canonicalize()
-                    .unwrap();
-                let s = git_root.to_str().unwrap();
-
-                // Bootstrap is quite bad at handling /? in front of paths
-                let git_root = match s.strip_prefix("\\\\?\\") {
-                    Some(p) => PathBuf::from(p),
-                    None => git_root,
-                };
-                // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
-                // for example, the build directory is inside of another unrelated git directory.
-                // In that case keep the original `CARGO_MANIFEST_DIR` handling.
-                //
-                // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
-                // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
-                if git_root.join("src").join("stage0").exists() {
-                    config.src = git_root;
-                }
-            } else {
-                // We're building from a tarball, not git sources.
-                // We don't support pre-downloaded bootstrap in this case.
-            }
-        }
-
         if cfg!(test) {
             // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly.
             config.out = Path::new(
@@ -556,220 +740,11 @@ impl Config {
             .to_path_buf();
         }
 
+        config.compiletest_allow_stage0 = build_compiletest_allow_stage0.unwrap_or(false);
         config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file();
 
-        // Locate the configuration file using the following priority (first match wins):
-        // 1. `--config <path>` (explicit flag)
-        // 2. `RUST_BOOTSTRAP_CONFIG` environment variable
-        // 3. `./bootstrap.toml` (local file)
-        // 4. `<root>/bootstrap.toml`
-        // 5. `./config.toml` (fallback for backward compatibility)
-        // 6. `<root>/config.toml`
-        let toml_path = flags_config
-            .clone()
-            .or_else(|| env::var_os("RUST_BOOTSTRAP_CONFIG").map(PathBuf::from));
-        let using_default_path = toml_path.is_none();
-        let mut toml_path = toml_path.unwrap_or_else(|| PathBuf::from("bootstrap.toml"));
-
-        if using_default_path && !toml_path.exists() {
-            toml_path = config.src.join(PathBuf::from("bootstrap.toml"));
-            if !toml_path.exists() {
-                toml_path = PathBuf::from("config.toml");
-                if !toml_path.exists() {
-                    toml_path = config.src.join(PathBuf::from("config.toml"));
-                }
-            }
-        }
-
-        // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
-        // but not if `bootstrap.toml` hasn't been created.
-        let mut toml = if !using_default_path || toml_path.exists() {
-            config.config = Some(if cfg!(not(test)) {
-                toml_path = toml_path.canonicalize().unwrap();
-                toml_path.clone()
-            } else {
-                toml_path.clone()
-            });
-            get_toml(&toml_path).unwrap_or_else(|e| {
-                eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
-                exit!(2);
-            })
-        } else {
-            config.config = None;
-            TomlConfig::default()
-        };
-
-        if cfg!(test) {
-            // When configuring bootstrap for tests, make sure to set the rustc and Cargo to the
-            // same ones used to call the tests (if custom ones are not defined in the toml). If we
-            // don't do that, bootstrap will use its own detection logic to find a suitable rustc
-            // and Cargo, which doesn't work when the caller is specìfying a custom local rustc or
-            // Cargo in their bootstrap.toml.
-            let build = toml.build.get_or_insert_with(Default::default);
-            build.rustc = build.rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into()));
-            build.cargo = build.cargo.take().or(std::env::var_os("CARGO").map(|p| p.into()));
-        }
-
-        if config.git_info(false, &config.src).is_from_tarball() && toml.profile.is_none() {
-            toml.profile = Some("dist".into());
-        }
-
-        // Reverse the list to ensure the last added config extension remains the most dominant.
-        // For example, given ["a.toml", "b.toml"], "b.toml" should take precedence over "a.toml".
-        //
-        // This must be handled before applying the `profile` since `include`s should always take
-        // precedence over `profile`s.
-        for include_path in toml.include.clone().unwrap_or_default().iter().rev() {
-            let include_path = toml_path.parent().unwrap().join(include_path);
-
-            let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
-                eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
-                exit!(2);
-            });
-            toml.merge(
-                Some(include_path),
-                &mut Default::default(),
-                included_toml,
-                ReplaceOpt::IgnoreDuplicate,
-            );
-        }
-
-        if let Some(include) = &toml.profile {
-            // Allows creating alias for profile names, allowing
-            // profiles to be renamed while maintaining back compatibility
-            // Keep in sync with `profile_aliases` in bootstrap.py
-            let profile_aliases = HashMap::from([("user", "dist")]);
-            let include = match profile_aliases.get(include.as_str()) {
-                Some(alias) => alias,
-                None => include.as_str(),
-            };
-            let mut include_path = config.src.clone();
-            include_path.push("src");
-            include_path.push("bootstrap");
-            include_path.push("defaults");
-            include_path.push(format!("bootstrap.{include}.toml"));
-            let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
-                eprintln!(
-                    "ERROR: Failed to parse default config profile at '{}': {e}",
-                    include_path.display()
-                );
-                exit!(2);
-            });
-            toml.merge(
-                Some(include_path),
-                &mut Default::default(),
-                included_toml,
-                ReplaceOpt::IgnoreDuplicate,
-            );
-        }
-
-        let mut override_toml = TomlConfig::default();
-        for option in flags_set.iter() {
-            fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
-                toml::from_str(option).and_then(|table: toml::Value| TomlConfig::deserialize(table))
-            }
-
-            let mut err = match get_table(option) {
-                Ok(v) => {
-                    override_toml.merge(
-                        None,
-                        &mut Default::default(),
-                        v,
-                        ReplaceOpt::ErrorOnDuplicate,
-                    );
-                    continue;
-                }
-                Err(e) => e,
-            };
-            // We want to be able to set string values without quotes,
-            // like in `configure.py`. Try adding quotes around the right hand side
-            if let Some((key, value)) = option.split_once('=')
-                && !value.contains('"')
-            {
-                match get_table(&format!(r#"{key}="{value}""#)) {
-                    Ok(v) => {
-                        override_toml.merge(
-                            None,
-                            &mut Default::default(),
-                            v,
-                            ReplaceOpt::ErrorOnDuplicate,
-                        );
-                        continue;
-                    }
-                    Err(e) => err = e,
-                }
-            }
-            eprintln!("failed to parse override `{option}`: `{err}");
-            exit!(2)
-        }
-        toml.merge(None, &mut Default::default(), override_toml, ReplaceOpt::Override);
-
         config.change_id = toml.change_id.inner;
 
-        let Build {
-            description,
-            build,
-            host,
-            target,
-            build_dir,
-            cargo,
-            rustc,
-            rustfmt,
-            cargo_clippy,
-            docs,
-            compiler_docs,
-            library_docs_private_items,
-            docs_minification,
-            submodules,
-            gdb,
-            lldb,
-            nodejs,
-            npm,
-            python,
-            reuse,
-            locked_deps,
-            vendor,
-            full_bootstrap,
-            bootstrap_cache_path,
-            extended,
-            tools,
-            tool,
-            verbose,
-            sanitizers,
-            profiler,
-            cargo_native_static,
-            low_priority,
-            configure_args,
-            local_rebuild,
-            print_step_timings,
-            print_step_rusage,
-            check_stage,
-            doc_stage,
-            build_stage,
-            test_stage,
-            install_stage,
-            dist_stage,
-            bench_stage,
-            patch_binaries_for_nix,
-            // This field is only used by bootstrap.py
-            metrics: _,
-            android_ndk,
-            optimized_compiler_builtins,
-            jobs,
-            compiletest_diff_tool,
-            compiletest_allow_stage0,
-            compiletest_use_stage0_libtest,
-            tidy_extra_checks,
-            ccache,
-            exclude,
-        } = toml.build.unwrap_or_default();
-
-        let mut paths: Vec<PathBuf> = flags_skip.into_iter().chain(flags_exclude).collect();
-
-        if let Some(exclude) = exclude {
-            paths.extend(exclude);
-        }
-
         config.skip = paths
             .into_iter()
             .map(|p| {
@@ -784,15 +759,20 @@ impl Config {
             })
             .collect();
 
-        config.jobs = Some(threads_from_config(flags_jobs.unwrap_or(jobs.unwrap_or(0))));
+        #[cfg(feature = "tracing")]
+        span!(
+            target: "CONFIG_HANDLING",
+            tracing::Level::TRACE,
+            "normalizing and combining `flag.skip`/`flag.exclude` paths",
+            "config.skip" = ?config.skip,
+        );
 
-        if let Some(flags_build) = flags_build {
-            config.host_target = TargetSelection::from_user(&flags_build);
-        } else if let Some(file_build) = build {
-            config.host_target = TargetSelection::from_user(&file_build);
-        };
+        config.jobs = Some(threads_from_config(build_jobs.unwrap_or(0)));
+        if let Some(build) = build_build {
+            config.host_target = TargetSelection::from_user(&build);
+        }
 
-        set(&mut config.out, flags_build_dir.or_else(|| build_dir.map(PathBuf::from)));
+        set(&mut config.out, build_dir);
         // NOTE: Bootstrap spawns various commands with different working directories.
         // To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
         if !config.out.is_absolute() {
@@ -800,21 +780,13 @@ impl Config {
             config.out = absolute(&config.out).expect("can't make empty path absolute");
         }
 
-        if cargo_clippy.is_some() && rustc.is_none() {
+        if build_cargo_clippy.is_some() && build_rustc.is_none() {
             println!(
                 "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
             );
         }
 
-        config.patch_binaries_for_nix = patch_binaries_for_nix;
-        config.bootstrap_cache_path = bootstrap_cache_path;
-        config.llvm_assertions =
-            toml.llvm.as_ref().is_some_and(|llvm| llvm.assertions.unwrap_or(false));
-
-        config.initial_rustc = if let Some(rustc) = rustc {
-            if !flags_skip_stage0_validation {
-                config.check_stage0_version(&rustc, "rustc");
-            }
+        config.initial_rustc = if let Some(rustc) = build_rustc {
             rustc
         } else {
             let dwn_ctx = DownloadContext::from(&config);
@@ -836,12 +808,9 @@ impl Config {
                 .trim()
         ));
 
-        config.initial_cargo_clippy = cargo_clippy;
+        config.initial_cargo_clippy = build_cargo_clippy;
 
-        config.initial_cargo = if let Some(cargo) = cargo {
-            if !flags_skip_stage0_validation {
-                config.check_stage0_version(&cargo, "cargo");
-            }
+        config.initial_cargo = if let Some(cargo) = build_cargo {
             cargo
         } else {
             let dwn_ctx = DownloadContext::from(&config);
@@ -856,62 +825,60 @@ impl Config {
             config.out = dir;
         }
 
-        config.hosts = if let Some(TargetSelectionList(arg_host)) = flags_host {
-            arg_host
-        } else if let Some(file_host) = host {
-            file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
-        } else {
-            vec![config.host_target]
-        };
-        config.targets = if let Some(TargetSelectionList(arg_target)) = flags_target {
-            arg_target
-        } else if let Some(file_target) = target {
-            file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
+        config.hosts = if let Some(hosts) = host { hosts } else { vec![config.host_target] };
+        config.targets = if let Some(targets) = target {
+            targets
         } else {
             // If target is *not* configured, then default to the host
             // toolchains.
             config.hosts.clone()
         };
 
-        config.nodejs = nodejs.map(PathBuf::from);
-        config.npm = npm.map(PathBuf::from);
-        config.gdb = gdb.map(PathBuf::from);
-        config.lldb = lldb.map(PathBuf::from);
-        config.python = python.map(PathBuf::from);
-        config.reuse = reuse.map(PathBuf::from);
-        config.submodules = submodules;
-        config.android_ndk = android_ndk;
-        set(&mut config.low_priority, low_priority);
-        set(&mut config.compiler_docs, compiler_docs);
-        set(&mut config.library_docs_private_items, library_docs_private_items);
-        set(&mut config.docs_minification, docs_minification);
-        set(&mut config.docs, docs);
-        set(&mut config.locked_deps, locked_deps);
-        set(&mut config.full_bootstrap, full_bootstrap);
-        set(&mut config.extended, extended);
-        config.tools = tools;
-        set(&mut config.tool, tool);
-        set(&mut config.verbose, verbose);
-        set(&mut config.sanitizers, sanitizers);
-        set(&mut config.profiler, profiler);
-        set(&mut config.cargo_native_static, cargo_native_static);
-        set(&mut config.configure_args, configure_args);
-        set(&mut config.local_rebuild, local_rebuild);
-        set(&mut config.print_step_timings, print_step_timings);
-        set(&mut config.print_step_rusage, print_step_rusage);
-
-        config.verbose = cmp::max(config.verbose, flags_verbose as usize);
+        config.nodejs = build_nodejs.map(PathBuf::from);
+        config.npm = build_npm.map(PathBuf::from);
+        config.gdb = build_gdb.map(PathBuf::from);
+        config.lldb = build_lldb.map(PathBuf::from);
+        config.python = build_python.map(PathBuf::from);
+        config.reuse = build_reuse.map(PathBuf::from);
+        config.submodules = build_submodules;
+        config.android_ndk = build_android_ndk;
+        config.bootstrap_cache_path = build_bootstrap_cache_path;
+        set(&mut config.low_priority, build_low_priority);
+        set(&mut config.compiler_docs, build_compiler_docs);
+        set(&mut config.library_docs_private_items, build_library_docs_private_items);
+        set(&mut config.docs_minification, build_docs_minification);
+        set(&mut config.docs, build_docs);
+        set(&mut config.locked_deps, build_locked_deps);
+        set(&mut config.full_bootstrap, build_full_bootstrap);
+        set(&mut config.extended, build_extended);
+        config.tools = build_tools;
+        set(&mut config.tool, build_tool);
+        set(&mut config.sanitizers, build_sanitizers);
+        set(&mut config.profiler, build_profiler);
+        set(&mut config.cargo_native_static, build_cargo_native_static);
+        set(&mut config.configure_args, build_configure_args);
+        set(&mut config.local_rebuild, build_local_rebuild);
+        set(&mut config.print_step_timings, build_print_step_timings);
+        set(&mut config.print_step_rusage, build_print_step_rusage);
+        config.patch_binaries_for_nix = build_patch_binaries_for_nix;
 
         // Verbose flag is a good default for `rust.verbose-tests`.
         config.verbose_tests = config.is_verbose();
 
-        config.apply_install_config(toml.install);
+        config.prefix = install_prefix.map(PathBuf::from);
+        config.sysconfdir = install_sysconfdir.map(PathBuf::from);
+        config.datadir = install_datadir.map(PathBuf::from);
+        config.docdir = install_docdir.map(PathBuf::from);
+        set(&mut config.bindir, install_bindir.map(PathBuf::from));
+        config.libdir = install_libdir.map(PathBuf::from);
+        config.mandir = install_mandir.map(PathBuf::from);
+
+        config.llvm_assertions = llvm_assertions.unwrap_or(false);
 
         let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel")));
         let ci_channel = file_content.trim_end();
 
-        let toml_channel = toml.rust.as_ref().and_then(|r| r.channel.clone());
-        let is_user_configured_rust_channel = match toml_channel {
+        let is_user_configured_rust_channel = match rust_channel {
             Some(channel) if channel == "auto-detect" => {
                 config.channel = ci_channel.into();
                 true
@@ -924,7 +891,7 @@ impl Config {
         };
 
         let default = config.channel == "dev";
-        config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default);
+        config.omit_git_hash = rust_omit_git_hash.unwrap_or(default);
 
         config.rust_info = config.git_info(config.omit_git_hash, &config.src);
         config.cargo_info =
@@ -942,7 +909,7 @@ impl Config {
         config.in_tree_llvm_info = config.git_info(false, &config.src.join("src/llvm-project"));
         config.in_tree_gcc_info = config.git_info(false, &config.src.join("src/gcc"));
 
-        config.vendor = vendor.unwrap_or(
+        config.vendor = build_vendor.unwrap_or(
             config.rust_info.is_from_tarball()
                 && config.src.join("vendor").exists()
                 && config.src.join(".cargo/config.toml").exists(),
@@ -955,11 +922,230 @@ impl Config {
         config.rust_profile_use = flags_rust_profile_use;
         config.rust_profile_generate = flags_rust_profile_generate;
 
-        config.apply_target_config(toml.target);
-        config.apply_rust_config(toml.rust, flags_warnings);
+        // FIXME(#133381): alt rustc builds currently do *not* have rustc debug assertions
+        // enabled. We should not download a CI alt rustc if we need rustc to have debug
+        // assertions (e.g. for crashes test suite). This can be changed once something like
+        // [Enable debug assertions on alt
+        // builds](https://github.com/rust-lang/rust/pull/131077) lands.
+        //
+        // Note that `rust.debug = true` currently implies `rust.debug-assertions = true`!
+        //
+        // This relies also on the fact that the global default for `download-rustc` will be
+        // `false` if it's not explicitly set.
+        let debug_assertions_requested = matches!(rust_rustc_debug_assertions, Some(true))
+            || (matches!(rust_debug, Some(true))
+                && !matches!(rust_rustc_debug_assertions, Some(false)));
+
+        if debug_assertions_requested
+            && let Some(ref opt) = rust_download_rustc
+            && opt.is_string_or_true()
+        {
+            eprintln!(
+                "WARN: currently no CI rustc builds have rustc debug assertions \
+                        enabled. Please either set `rust.debug-assertions` to `false` if you \
+                        want to use download CI rustc or set `rust.download-rustc` to `false`."
+            );
+        }
+
+        config.download_rustc_commit = config.download_ci_rustc_commit(
+            rust_download_rustc,
+            debug_assertions_requested,
+            config.llvm_assertions,
+        );
+
+        if let Some(t) = toml.target {
+            for (triple, cfg) in t {
+                let mut target = Target::from_triple(&triple);
+
+                if let Some(ref s) = cfg.llvm_config {
+                    if config.download_rustc_commit.is_some()
+                        && triple == *config.host_target.triple
+                    {
+                        panic!(
+                            "setting llvm_config for the host is incompatible with download-rustc"
+                        );
+                    }
+                    target.llvm_config = Some(config.src.join(s));
+                }
+                if let Some(patches) = cfg.llvm_has_rust_patches {
+                    assert!(
+                        config.submodules == Some(false) || cfg.llvm_config.is_some(),
+                        "use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
+                    );
+                    target.llvm_has_rust_patches = Some(patches);
+                }
+                if let Some(ref s) = cfg.llvm_filecheck {
+                    target.llvm_filecheck = Some(config.src.join(s));
+                }
+                target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| {
+                    v.parse().unwrap_or_else(|_| {
+                        panic!("failed to parse target.{triple}.llvm-libunwind")
+                    })
+                });
+                if let Some(s) = cfg.no_std {
+                    target.no_std = s;
+                }
+                target.cc = cfg.cc.map(PathBuf::from);
+                target.cxx = cfg.cxx.map(PathBuf::from);
+                target.ar = cfg.ar.map(PathBuf::from);
+                target.ranlib = cfg.ranlib.map(PathBuf::from);
+                target.linker = cfg.linker.map(PathBuf::from);
+                target.crt_static = cfg.crt_static;
+                target.musl_root = cfg.musl_root.map(PathBuf::from);
+                target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
+                target.wasi_root = cfg.wasi_root.map(PathBuf::from);
+                target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
+                target.runner = cfg.runner;
+                target.sanitizers = cfg.sanitizers;
+                target.profiler = cfg.profiler;
+                target.rpath = cfg.rpath;
+                target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
+                target.jemalloc = cfg.jemalloc;
+                if let Some(backends) = cfg.codegen_backends {
+                    target.codegen_backends =
+                        Some(parse_codegen_backends(backends, &format!("target.{triple}")))
+                }
+
+                target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| {
+                    v.parse().unwrap_or_else(|_| {
+                        panic!("invalid value for target.{triple}.split-debuginfo")
+                    })
+                });
+
+                config.target_config.insert(TargetSelection::from_user(&triple), target);
+            }
+        }
+
+        if rust_optimize.as_ref().is_some_and(|v| matches!(v, RustOptimize::Bool(false))) {
+            eprintln!(
+                "WARNING: setting `optimize` to `false` is known to cause errors and \
+                should be considered unsupported. Refer to `bootstrap.example.toml` \
+                for more details."
+            );
+        }
+
+        config.rust_new_symbol_mangling = rust_new_symbol_mangling;
+        set(&mut config.rust_optimize_tests, rust_optimize_tests);
+        set(&mut config.codegen_tests, rust_codegen_tests);
+        set(&mut config.rust_rpath, rust_rpath);
+        set(&mut config.rust_strip, rust_strip);
+        set(&mut config.rust_frame_pointers, rust_frame_pointers);
+        config.rust_stack_protector = rust_stack_protector;
+        set(&mut config.jemalloc, rust_jemalloc);
+        set(&mut config.test_compare_mode, rust_test_compare_mode);
+        set(&mut config.backtrace, rust_backtrace);
+        set(&mut config.rust_dist_src, rust_dist_src);
+        set(&mut config.verbose_tests, rust_verbose_tests);
+        // in the case "false" is set explicitly, do not overwrite the command line args
+        if let Some(true) = rust_incremental {
+            config.incremental = true;
+        }
+        set(&mut config.lld_mode, rust_lld_mode);
+        set(&mut config.llvm_bitcode_linker_enabled, rust_llvm_bitcode_linker);
+
+        config.rust_randomize_layout = rust_randomize_layout.unwrap_or_default();
+        config.llvm_tools_enabled = rust_llvm_tools.unwrap_or(true);
+
+        config.llvm_enzyme = config.channel == "dev" || config.channel == "nightly";
+        config.rustc_default_linker = rust_default_linker;
+        config.musl_root = rust_musl_root.map(PathBuf::from);
+        config.save_toolstates = rust_save_toolstates.map(PathBuf::from);
+        set(
+            &mut config.deny_warnings,
+            match flags_warnings {
+                Warnings::Deny => Some(true),
+                Warnings::Warn => Some(false),
+                Warnings::Default => rust_deny_warnings,
+            },
+        );
+        set(&mut config.backtrace_on_ice, rust_backtrace_on_ice);
+        set(&mut config.rust_verify_llvm_ir, rust_verify_llvm_ir);
+        config.rust_thin_lto_import_instr_limit = rust_thin_lto_import_instr_limit;
+        set(&mut config.rust_remap_debuginfo, rust_remap_debuginfo);
+        set(&mut config.control_flow_guard, rust_control_flow_guard);
+        set(&mut config.ehcont_guard, rust_ehcont_guard);
+        config.llvm_libunwind_default =
+            rust_llvm_libunwind.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
+        set(
+            &mut config.rust_codegen_backends,
+            rust_codegen_backends.map(|backends| parse_codegen_backends(backends, "rust")),
+        );
+
+        config.rust_codegen_units = rust_codegen_units.map(threads_from_config);
+        config.rust_codegen_units_std = rust_codegen_units_std.map(threads_from_config);
+
+        if config.rust_profile_use.is_none() {
+            config.rust_profile_use = rust_profile_use;
+        }
+
+        if config.rust_profile_generate.is_none() {
+            config.rust_profile_generate = rust_profile_generate;
+        }
+
+        config.rust_lto =
+            rust_lto.as_deref().map(|value| RustcLto::from_str(value).unwrap()).unwrap_or_default();
+        config.rust_validate_mir_opts = rust_validate_mir_opts;
+
+        config.rust_optimize = rust_optimize.unwrap_or(RustOptimize::Bool(true));
+
+        // We make `x86_64-unknown-linux-gnu` use the self-contained linker by default, so we will
+        // build our internal lld and use it as the default linker, by setting the `rust.lld` config
+        // to true by default:
+        // - on the `x86_64-unknown-linux-gnu` target
+        // - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that
+        //   we're also able to build the corresponding lld
+        // - or when using an external llvm that's downloaded from CI, which also contains our prebuilt
+        //   lld
+        // - otherwise, we'd be using an external llvm, and lld would not necessarily available and
+        //   thus, disabled
+        // - similarly, lld will not be built nor used by default when explicitly asked not to, e.g.
+        //   when the config sets `rust.lld = false`
+        if default_lld_opt_in_targets().contains(&config.host_target.triple.to_string())
+            && config.hosts == [config.host_target]
+        {
+            let no_llvm_config = config
+                .target_config
+                .get(&config.host_target)
+                .is_none_or(|target_config| target_config.llvm_config.is_none());
+            let enable_lld = config.llvm_from_ci || no_llvm_config;
+            // Prefer the config setting in case an explicit opt-out is needed.
+            config.lld_enabled = rust_lld_enabled.unwrap_or(enable_lld);
+        } else {
+            set(&mut config.lld_enabled, rust_lld_enabled);
+        }
+
+        let default_std_features = BTreeSet::from([String::from("panic-unwind")]);
+        config.rust_std_features = rust_std_features.unwrap_or(default_std_features);
+
+        let default = rust_debug == Some(true);
+        config.rustc_debug_assertions = rust_rustc_debug_assertions.unwrap_or(default);
+        config.std_debug_assertions =
+            rust_std_debug_assertions.unwrap_or(config.rustc_debug_assertions);
+        config.tools_debug_assertions =
+            rust_tools_debug_assertions.unwrap_or(config.rustc_debug_assertions);
+        config.rust_overflow_checks = rust_overflow_checks.unwrap_or(default);
+        config.rust_overflow_checks_std =
+            rust_overflow_checks_std.unwrap_or(config.rust_overflow_checks);
+
+        config.rust_debug_logging = rust_debug_logging.unwrap_or(config.rustc_debug_assertions);
+
+        let with_defaults = |debuginfo_level_specific: Option<_>| {
+            debuginfo_level_specific.or(rust_debuginfo_level).unwrap_or(
+                if rust_debug == Some(true) {
+                    DebuginfoLevel::Limited
+                } else {
+                    DebuginfoLevel::None
+                },
+            )
+        };
+        config.rust_debuginfo_level_rustc = with_defaults(rust_debuginfo_level_rustc);
+        config.rust_debuginfo_level_std = with_defaults(rust_debuginfo_level_std);
+        config.rust_debuginfo_level_tools = with_defaults(rust_debuginfo_level_tools);
+        config.rust_debuginfo_level_tests =
+            rust_debuginfo_level_tests.unwrap_or(DebuginfoLevel::None);
 
         config.reproducible_artifacts = flags_reproducible_artifact;
-        config.description = description;
+        config.description = build_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 bootstrap.toml,
@@ -977,11 +1163,90 @@ impl Config {
             config.channel = channel;
         }
 
-        config.apply_llvm_config(toml.llvm);
+        set(&mut config.ninja_in_file, llvm_ninja);
+        set(&mut config.llvm_optimize, llvm_optimize);
+        set(&mut config.llvm_thin_lto, llvm_thin_lto);
+        set(&mut config.llvm_release_debuginfo, llvm_release_debuginfo);
+        set(&mut config.llvm_static_stdcpp, llvm_static_libstdcpp);
+        set(&mut config.llvm_libzstd, llvm_libzstd);
+        if let Some(v) = llvm_link_shared {
+            config.llvm_link_shared.set(Some(v));
+        }
+        config.llvm_targets.clone_from(&llvm_targets);
+        config.llvm_experimental_targets.clone_from(&llvm_experimental_targets);
+        config.llvm_link_jobs = llvm_link_jobs;
+        config.llvm_version_suffix.clone_from(&llvm_version_suffix);
+        config.llvm_clang_cl.clone_from(&llvm_clang_cl);
+        config.llvm_tests = llvm_tests.unwrap_or_default();
+        config.llvm_enzyme = llvm_enzyme.unwrap_or_default();
+        config.llvm_plugins = llvm_plugin.unwrap_or_default();
+
+        config.llvm_cflags.clone_from(&llvm_cflags);
+        config.llvm_cxxflags.clone_from(&llvm_cxxflags);
+        config.llvm_ldflags.clone_from(&llvm_ldflags);
+        set(&mut config.llvm_use_libcxx, llvm_use_libcxx);
+        config.llvm_use_linker.clone_from(&llvm_use_linker);
+        config.llvm_allow_old_toolchain = llvm_allow_old_toolchain.unwrap_or(false);
+        config.llvm_offload = llvm_offload.unwrap_or(false);
+        config.llvm_polly = llvm_polly.unwrap_or(false);
+        config.llvm_clang = llvm_clang.unwrap_or(false);
+        config.llvm_enable_warnings = llvm_enable_warnings.unwrap_or(false);
+        config.llvm_build_config = llvm_build_config.clone().unwrap_or(Default::default());
+
+        config.llvm_from_ci =
+            config.parse_download_ci_llvm(llvm_download_ci_llvm, config.llvm_assertions);
+
+        if config.llvm_from_ci {
+            let warn = |option: &str| {
+                println!(
+                    "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
+                );
+                println!(
+                    "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
+                );
+            };
+
+            if llvm_static_libstdcpp.is_some() {
+                warn("static-libstdcpp");
+            }
+
+            if llvm_link_shared.is_some() {
+                warn("link-shared");
+            }
+
+            // FIXME(#129153): instead of all the ad-hoc `download-ci-llvm` checks that follow,
+            // use the `builder-config` present in tarballs since #128822 to compare the local
+            // config to the ones used to build the LLVM artifacts on CI, and only notify users
+            // if they've chosen a different value.
+
+            if llvm_libzstd.is_some() {
+                println!(
+                    "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
+                    like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
+                    artifacts builder config."
+                );
+                println!(
+                    "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
+                );
+            }
+        }
+
+        if !config.llvm_from_ci && config.llvm_thin_lto && llvm_link_shared.is_none() {
+            // If we're building with ThinLTO on, by default we want to link
+            // to LLVM shared, to avoid re-doing ThinLTO (which happens in
+            // the link step) with each stage.
+            config.llvm_link_shared.set(Some(true));
+        }
 
-        config.apply_gcc_config(toml.gcc);
+        config.gcc_ci_mode = match gcc_download_ci_gcc {
+            Some(value) => match value {
+                true => GccCiMode::DownloadFromCi,
+                false => GccCiMode::BuildLocally,
+            },
+            None => GccCiMode::default(),
+        };
 
-        match ccache {
+        match build_ccache {
             Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
             Some(StringOrBool::Bool(true)) => {
                 config.ccache = Some("ccache".to_string());
@@ -1005,9 +1270,18 @@ impl Config {
                 Some(ci_llvm_bin.join(exe("FileCheck", config.host_target)));
         }
 
-        config.apply_dist_config(toml.dist);
+        config.dist_sign_folder = dist_sign_folder.map(PathBuf::from);
+        config.dist_upload_addr = dist_upload_addr;
+        config.dist_compression_formats = dist_compression_formats;
+        set(&mut config.dist_compression_profile, dist_compression_profile);
+        set(&mut config.rust_dist_src, dist_src_tarball);
+        set(&mut config.dist_include_mingw_linker, dist_include_mingw_linker);
+        config.dist_vendor = dist_vendor.unwrap_or_else(|| {
+            // If we're building from git or tarball sources, enable it by default.
+            config.rust_info.is_managed_git_subrepository() || config.rust_info.is_from_tarball()
+        });
 
-        config.initial_rustfmt = if let Some(r) = rustfmt {
+        config.initial_rustfmt = if let Some(r) = build_rustfmt {
             Some(r)
         } else {
             let dwn_ctx = DownloadContext::from(&config);
@@ -1028,41 +1302,40 @@ impl Config {
         }
 
         config.optimized_compiler_builtins =
-            optimized_compiler_builtins.unwrap_or(config.channel != "dev");
-
-        config.compiletest_diff_tool = compiletest_diff_tool;
-
-        config.compiletest_allow_stage0 = compiletest_allow_stage0.unwrap_or(false);
-        config.compiletest_use_stage0_libtest = compiletest_use_stage0_libtest.unwrap_or(true);
-
-        config.tidy_extra_checks = tidy_extra_checks;
+            build_optimized_compiler_builtins.unwrap_or(config.channel != "dev");
+        config.compiletest_diff_tool = build_compiletest_diff_tool;
+        config.compiletest_use_stage0_libtest =
+            build_compiletest_use_stage0_libtest.unwrap_or(true);
+        config.tidy_extra_checks = build_tidy_extra_checks;
 
         let download_rustc = config.download_rustc_commit.is_some();
         config.explicit_stage_from_cli = flags_stage.is_some();
-        config.explicit_stage_from_config = test_stage.is_some()
-            || build_stage.is_some()
-            || doc_stage.is_some()
-            || dist_stage.is_some()
-            || install_stage.is_some()
-            || check_stage.is_some()
-            || bench_stage.is_some();
+        config.explicit_stage_from_config = build_test_stage.is_some()
+            || build_build_stage.is_some()
+            || build_doc_stage.is_some()
+            || build_dist_stage.is_some()
+            || build_install_stage.is_some()
+            || build_check_stage.is_some()
+            || build_bench_stage.is_some();
 
         config.stage = match config.cmd {
-            Subcommand::Check { .. } => flags_stage.or(check_stage).unwrap_or(1),
-            Subcommand::Clippy { .. } | Subcommand::Fix => flags_stage.or(check_stage).unwrap_or(1),
+            Subcommand::Check { .. } => flags_stage.or(build_check_stage).unwrap_or(1),
+            Subcommand::Clippy { .. } | Subcommand::Fix => {
+                flags_stage.or(build_check_stage).unwrap_or(1)
+            }
             // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden.
             Subcommand::Doc { .. } => {
-                flags_stage.or(doc_stage).unwrap_or(if download_rustc { 2 } else { 1 })
+                flags_stage.or(build_doc_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
             Subcommand::Build => {
-                flags_stage.or(build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
+                flags_stage.or(build_build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
             Subcommand::Test { .. } | Subcommand::Miri { .. } => {
-                flags_stage.or(test_stage).unwrap_or(if download_rustc { 2 } else { 1 })
+                flags_stage.or(build_test_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
-            Subcommand::Bench { .. } => flags_stage.or(bench_stage).unwrap_or(2),
-            Subcommand::Dist => flags_stage.or(dist_stage).unwrap_or(2),
-            Subcommand::Install => flags_stage.or(install_stage).unwrap_or(2),
+            Subcommand::Bench { .. } => flags_stage.or(build_bench_stage).unwrap_or(2),
+            Subcommand::Dist => flags_stage.or(build_dist_stage).unwrap_or(2),
+            Subcommand::Install => flags_stage.or(build_install_stage).unwrap_or(2),
             Subcommand::Perf { .. } => flags_stage.unwrap_or(1),
             // These are all bootstrap tools, which don't depend on the compiler.
             // The stage we pass shouldn't matter, but use 0 just in case.
@@ -1512,49 +1785,6 @@ impl Config {
         }
     }
 
-    #[cfg(test)]
-    pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {}
-
-    /// check rustc/cargo version is same or lower with 1 apart from the building one
-    #[cfg(not(test))]
-    pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) {
-        use build_helper::util::fail;
-
-        if self.dry_run() {
-            return;
-        }
-
-        let stage0_output =
-            command(program_path).arg("--version").run_capture_stdout(self).stdout();
-        let mut stage0_output = stage0_output.lines().next().unwrap().split(' ');
-
-        let stage0_name = stage0_output.next().unwrap();
-        if stage0_name != component_name {
-            fail(&format!(
-                "Expected to find {component_name} at {} but it claims to be {stage0_name}",
-                program_path.display()
-            ));
-        }
-
-        let stage0_version =
-            semver::Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
-                .unwrap();
-        let source_version = semver::Version::parse(
-            fs::read_to_string(self.src.join("src/version")).unwrap().trim(),
-        )
-        .unwrap();
-        if !(source_version == stage0_version
-            || (source_version.major == stage0_version.major
-                && (source_version.minor == stage0_version.minor
-                    || source_version.minor == stage0_version.minor + 1)))
-        {
-            let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
-            fail(&format!(
-                "Unexpected {component_name} version: {stage0_version}, we should use {prev_version}/{source_version} to build source with {source_version}"
-            ));
-        }
-    }
-
     /// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
     pub fn download_ci_rustc_commit(
         &self,
@@ -1846,3 +2076,262 @@ impl AsRef<ExecutionContext> for Config {
         &self.exec_ctx
     }
 }
+
+fn compute_src_directory(src_dir: Option<PathBuf>, exec_ctx: &ExecutionContext) -> Option<PathBuf> {
+    if let Some(src) = src_dir {
+        return Some(src);
+    } else {
+        // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
+        // running on a completely different machine from where it was compiled.
+        let mut cmd = helpers::git(None);
+        // NOTE: we cannot support running from outside the repository because the only other path we have available
+        // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.
+        // We still support running outside the repository if we find we aren't in a git directory.
+
+        // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,
+        // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap
+        // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
+        cmd.arg("rev-parse").arg("--show-cdup");
+        // Discard stderr because we expect this to fail when building from a tarball.
+        let output = cmd.allow_failure().run_capture_stdout(exec_ctx);
+        if output.is_success() {
+            let git_root_relative = output.stdout();
+            // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
+            // and to resolve any relative components.
+            let git_root = env::current_dir()
+                .unwrap()
+                .join(PathBuf::from(git_root_relative.trim()))
+                .canonicalize()
+                .unwrap();
+            let s = git_root.to_str().unwrap();
+
+            // Bootstrap is quite bad at handling /? in front of paths
+            let git_root = match s.strip_prefix("\\\\?\\") {
+                Some(p) => PathBuf::from(p),
+                None => git_root,
+            };
+            // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
+            // for example, the build directory is inside of another unrelated git directory.
+            // In that case keep the original `CARGO_MANIFEST_DIR` handling.
+            //
+            // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
+            // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
+            if git_root.join("src").join("stage0").exists() {
+                return Some(git_root);
+            }
+        } else {
+            // We're building from a tarball, not git sources.
+            // We don't support pre-downloaded bootstrap in this case.
+        }
+    };
+    None
+}
+
+/// Loads bootstrap TOML config and returns the config together with a path from where
+/// it was loaded.
+/// `src` is the source root directory, and `config_path` is an optionally provided path to the
+/// config.
+fn load_toml_config(
+    src: &Path,
+    config_path: Option<PathBuf>,
+    get_toml: &impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>,
+) -> (TomlConfig, Option<PathBuf>) {
+    // Locate the configuration file using the following priority (first match wins):
+    // 1. `--config <path>` (explicit flag)
+    // 2. `RUST_BOOTSTRAP_CONFIG` environment variable
+    // 3. `./bootstrap.toml` (local file)
+    // 4. `<root>/bootstrap.toml`
+    // 5. `./config.toml` (fallback for backward compatibility)
+    // 6. `<root>/config.toml`
+    let toml_path = config_path.or_else(|| env::var_os("RUST_BOOTSTRAP_CONFIG").map(PathBuf::from));
+    let using_default_path = toml_path.is_none();
+    let mut toml_path = toml_path.unwrap_or_else(|| PathBuf::from("bootstrap.toml"));
+
+    if using_default_path && !toml_path.exists() {
+        toml_path = src.join(PathBuf::from("bootstrap.toml"));
+        if !toml_path.exists() {
+            toml_path = PathBuf::from("config.toml");
+            if !toml_path.exists() {
+                toml_path = src.join(PathBuf::from("config.toml"));
+            }
+        }
+    }
+
+    // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
+    // but not if `bootstrap.toml` hasn't been created.
+    if !using_default_path || toml_path.exists() {
+        let path = Some(if cfg!(not(test)) {
+            toml_path = toml_path.canonicalize().unwrap();
+            toml_path.clone()
+        } else {
+            toml_path.clone()
+        });
+        (
+            get_toml(&toml_path).unwrap_or_else(|e| {
+                eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
+                exit!(2);
+            }),
+            path,
+        )
+    } else {
+        (TomlConfig::default(), None)
+    }
+}
+
+fn postprocess_toml(
+    toml: &mut TomlConfig,
+    src_dir: &Path,
+    toml_path: Option<PathBuf>,
+    exec_ctx: &ExecutionContext,
+    override_set: &[String],
+    get_toml: &impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>,
+) {
+    let git_info = GitInfo::new(false, src_dir, exec_ctx);
+
+    if git_info.is_from_tarball() && toml.profile.is_none() {
+        toml.profile = Some("dist".into());
+    }
+
+    // Reverse the list to ensure the last added config extension remains the most dominant.
+    // For example, given ["a.toml", "b.toml"], "b.toml" should take precedence over "a.toml".
+    //
+    // This must be handled before applying the `profile` since `include`s should always take
+    // precedence over `profile`s.
+    for include_path in toml.include.clone().unwrap_or_default().iter().rev() {
+        let include_path = toml_path
+            .as_ref()
+            .expect("include found in default TOML config")
+            .parent()
+            .unwrap()
+            .join(include_path);
+
+        let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
+            eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
+            exit!(2);
+        });
+        toml.merge(
+            Some(include_path),
+            &mut Default::default(),
+            included_toml,
+            ReplaceOpt::IgnoreDuplicate,
+        );
+    }
+
+    if let Some(include) = &toml.profile {
+        // Allows creating alias for profile names, allowing
+        // profiles to be renamed while maintaining back compatibility
+        // Keep in sync with `profile_aliases` in bootstrap.py
+        let profile_aliases = HashMap::from([("user", "dist")]);
+        let include = match profile_aliases.get(include.as_str()) {
+            Some(alias) => alias,
+            None => include.as_str(),
+        };
+        let mut include_path = PathBuf::from(src_dir);
+        include_path.push("src");
+        include_path.push("bootstrap");
+        include_path.push("defaults");
+        include_path.push(format!("bootstrap.{include}.toml"));
+        let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
+            eprintln!(
+                "ERROR: Failed to parse default config profile at '{}': {e}",
+                include_path.display()
+            );
+            exit!(2);
+        });
+        toml.merge(
+            Some(include_path),
+            &mut Default::default(),
+            included_toml,
+            ReplaceOpt::IgnoreDuplicate,
+        );
+    }
+
+    let mut override_toml = TomlConfig::default();
+    for option in override_set.iter() {
+        fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
+            toml::from_str(option).and_then(|table: toml::Value| TomlConfig::deserialize(table))
+        }
+
+        let mut err = match get_table(option) {
+            Ok(v) => {
+                override_toml.merge(None, &mut Default::default(), v, ReplaceOpt::ErrorOnDuplicate);
+                continue;
+            }
+            Err(e) => e,
+        };
+        // We want to be able to set string values without quotes,
+        // like in `configure.py`. Try adding quotes around the right hand side
+        if let Some((key, value)) = option.split_once('=')
+            && !value.contains('"')
+        {
+            match get_table(&format!(r#"{key}="{value}""#)) {
+                Ok(v) => {
+                    override_toml.merge(
+                        None,
+                        &mut Default::default(),
+                        v,
+                        ReplaceOpt::ErrorOnDuplicate,
+                    );
+                    continue;
+                }
+                Err(e) => err = e,
+            }
+        }
+        eprintln!("failed to parse override `{option}`: `{err}");
+        exit!(2)
+    }
+    toml.merge(None, &mut Default::default(), override_toml, ReplaceOpt::Override);
+}
+
+#[cfg(test)]
+pub fn check_stage0_version(
+    _program_path: &Path,
+    _component_name: &'static str,
+    _src_dir: &Path,
+    _exec_ctx: &ExecutionContext,
+) {
+}
+
+/// check rustc/cargo version is same or lower with 1 apart from the building one
+#[cfg(not(test))]
+pub fn check_stage0_version(
+    program_path: &Path,
+    component_name: &'static str,
+    src_dir: &Path,
+    exec_ctx: &ExecutionContext,
+) {
+    use build_helper::util::fail;
+
+    if exec_ctx.dry_run() {
+        return;
+    }
+
+    let stage0_output =
+        command(program_path).arg("--version").run_capture_stdout(exec_ctx).stdout();
+    let mut stage0_output = stage0_output.lines().next().unwrap().split(' ');
+
+    let stage0_name = stage0_output.next().unwrap();
+    if stage0_name != component_name {
+        fail(&format!(
+            "Expected to find {component_name} at {} but it claims to be {stage0_name}",
+            program_path.display()
+        ));
+    }
+
+    let stage0_version =
+        semver::Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
+            .unwrap();
+    let source_version =
+        semver::Version::parse(fs::read_to_string(src_dir.join("src/version")).unwrap().trim())
+            .unwrap();
+    if !(source_version == stage0_version
+        || (source_version.major == stage0_version.major
+            && (source_version.minor == stage0_version.minor
+                || source_version.minor == stage0_version.minor + 1)))
+    {
+        let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
+        fail(&format!(
+            "Unexpected {component_name} version: {stage0_version}, we should use {prev_version}/{source_version} to build source with {source_version}"
+        ));
+    }
+}
diff --git a/src/bootstrap/src/core/config/toml/dist.rs b/src/bootstrap/src/core/config/toml/dist.rs
index b1429ef1861..934d64d8899 100644
--- a/src/bootstrap/src/core/config/toml/dist.rs
+++ b/src/bootstrap/src/core/config/toml/dist.rs
@@ -7,11 +7,12 @@
 
 use serde::{Deserialize, Deserializer};
 
+use crate::core::config::Merge;
 use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{Merge, set};
-use crate::{Config, HashSet, PathBuf, define_config, exit};
+use crate::{HashSet, PathBuf, define_config, exit};
 
 define_config! {
+    #[derive(Default)]
     struct Dist {
         sign_folder: Option<String> = "sign-folder",
         upload_addr: Option<String> = "upload-addr",
@@ -22,31 +23,3 @@ define_config! {
         vendor: Option<bool> = "vendor",
     }
 }
-
-impl Config {
-    /// Applies distribution-related configuration from the `Dist` struct
-    /// to the global `Config` structure.
-    pub fn apply_dist_config(&mut self, toml_dist: Option<Dist>) {
-        if let Some(dist) = toml_dist {
-            let Dist {
-                sign_folder,
-                upload_addr,
-                src_tarball,
-                compression_formats,
-                compression_profile,
-                include_mingw_linker,
-                vendor,
-            } = dist;
-            self.dist_sign_folder = sign_folder.map(PathBuf::from);
-            self.dist_upload_addr = upload_addr;
-            self.dist_compression_formats = compression_formats;
-            set(&mut self.dist_compression_profile, compression_profile);
-            set(&mut self.rust_dist_src, src_tarball);
-            set(&mut self.dist_include_mingw_linker, include_mingw_linker);
-            self.dist_vendor = vendor.unwrap_or_else(|| {
-                // If we're building from git or tarball sources, enable it by default.
-                self.rust_info.is_managed_git_subrepository() || self.rust_info.is_from_tarball()
-            });
-        }
-    }
-}
diff --git a/src/bootstrap/src/core/config/toml/gcc.rs b/src/bootstrap/src/core/config/toml/gcc.rs
index bb817c2aaef..9ea697edf15 100644
--- a/src/bootstrap/src/core/config/toml/gcc.rs
+++ b/src/bootstrap/src/core/config/toml/gcc.rs
@@ -6,29 +6,14 @@
 
 use serde::{Deserialize, Deserializer};
 
+use crate::core::config::Merge;
 use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{GccCiMode, Merge};
-use crate::{Config, HashSet, PathBuf, define_config, exit};
+use crate::{HashSet, PathBuf, define_config, exit};
 
 define_config! {
     /// TOML representation of how the GCC build is configured.
+    #[derive(Default)]
     struct Gcc {
         download_ci_gcc: Option<bool> = "download-ci-gcc",
     }
 }
-
-impl Config {
-    /// Applies GCC-related configuration from the `TomlGcc` struct to the
-    /// global `Config` structure.
-    pub fn apply_gcc_config(&mut self, toml_gcc: Option<Gcc>) {
-        if let Some(gcc) = toml_gcc {
-            self.gcc_ci_mode = match gcc.download_ci_gcc {
-                Some(value) => match value {
-                    true => GccCiMode::DownloadFromCi,
-                    false => GccCiMode::BuildLocally,
-                },
-                None => GccCiMode::default(),
-            };
-        }
-    }
-}
diff --git a/src/bootstrap/src/core/config/toml/install.rs b/src/bootstrap/src/core/config/toml/install.rs
index 6b9ab87a0b6..60fa958bd82 100644
--- a/src/bootstrap/src/core/config/toml/install.rs
+++ b/src/bootstrap/src/core/config/toml/install.rs
@@ -8,12 +8,13 @@
 
 use serde::{Deserialize, Deserializer};
 
+use crate::core::config::Merge;
 use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{Merge, set};
-use crate::{Config, HashSet, PathBuf, define_config, exit};
+use crate::{HashSet, PathBuf, define_config, exit};
 
 define_config! {
     /// TOML representation of various global install decisions.
+    #[derive(Default)]
     struct Install {
         prefix: Option<String> = "prefix",
         sysconfdir: Option<String> = "sysconfdir",
@@ -24,20 +25,3 @@ define_config! {
         datadir: Option<String> = "datadir",
     }
 }
-
-impl Config {
-    /// Applies installation-related configuration from the `Install` struct
-    /// to the global `Config` structure.
-    pub fn apply_install_config(&mut self, toml_install: Option<Install>) {
-        if let Some(install) = toml_install {
-            let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install;
-            self.prefix = prefix.map(PathBuf::from);
-            self.sysconfdir = sysconfdir.map(PathBuf::from);
-            self.datadir = datadir.map(PathBuf::from);
-            self.docdir = docdir.map(PathBuf::from);
-            set(&mut self.bindir, bindir.map(PathBuf::from));
-            self.libdir = libdir.map(PathBuf::from);
-            self.mandir = mandir.map(PathBuf::from);
-        }
-    }
-}
diff --git a/src/bootstrap/src/core/config/toml/llvm.rs b/src/bootstrap/src/core/config/toml/llvm.rs
index 1f0cecd145c..9751837a887 100644
--- a/src/bootstrap/src/core/config/toml/llvm.rs
+++ b/src/bootstrap/src/core/config/toml/llvm.rs
@@ -3,12 +3,13 @@
 
 use serde::{Deserialize, Deserializer};
 
+use crate::core::config::StringOrBool;
 use crate::core::config::toml::{Merge, ReplaceOpt, TomlConfig};
-use crate::core::config::{StringOrBool, set};
-use crate::{Config, HashMap, HashSet, PathBuf, define_config, exit};
+use crate::{HashMap, HashSet, PathBuf, define_config, exit};
 
 define_config! {
     /// TOML representation of how the LLVM build is configured.
+    #[derive(Default)]
     struct Llvm {
         optimize: Option<bool> = "optimize",
         thin_lto: Option<bool> = "thin-lto",
@@ -144,127 +145,3 @@ pub fn check_incompatible_options_for_ci_llvm(
 
     Ok(())
 }
-
-impl Config {
-    pub fn apply_llvm_config(&mut self, toml_llvm: Option<Llvm>) {
-        let mut llvm_tests = None;
-        let mut llvm_enzyme = None;
-        let mut llvm_offload = None;
-        let mut llvm_plugins = None;
-
-        if let Some(llvm) = toml_llvm {
-            let Llvm {
-                optimize: optimize_toml,
-                thin_lto,
-                release_debuginfo,
-                assertions: _,
-                tests,
-                enzyme,
-                plugins,
-                static_libstdcpp,
-                libzstd,
-                ninja,
-                targets,
-                experimental_targets,
-                link_jobs,
-                link_shared,
-                version_suffix,
-                clang_cl,
-                cflags,
-                cxxflags,
-                ldflags,
-                use_libcxx,
-                use_linker,
-                allow_old_toolchain,
-                offload,
-                polly,
-                clang,
-                enable_warnings,
-                download_ci_llvm,
-                build_config,
-            } = llvm;
-
-            set(&mut self.ninja_in_file, ninja);
-            llvm_tests = tests;
-            llvm_enzyme = enzyme;
-            llvm_offload = offload;
-            llvm_plugins = plugins;
-            set(&mut self.llvm_optimize, optimize_toml);
-            set(&mut self.llvm_thin_lto, thin_lto);
-            set(&mut self.llvm_release_debuginfo, release_debuginfo);
-            set(&mut self.llvm_static_stdcpp, static_libstdcpp);
-            set(&mut self.llvm_libzstd, libzstd);
-            if let Some(v) = link_shared {
-                self.llvm_link_shared.set(Some(v));
-            }
-            self.llvm_targets.clone_from(&targets);
-            self.llvm_experimental_targets.clone_from(&experimental_targets);
-            self.llvm_link_jobs = link_jobs;
-            self.llvm_version_suffix.clone_from(&version_suffix);
-            self.llvm_clang_cl.clone_from(&clang_cl);
-
-            self.llvm_cflags.clone_from(&cflags);
-            self.llvm_cxxflags.clone_from(&cxxflags);
-            self.llvm_ldflags.clone_from(&ldflags);
-            set(&mut self.llvm_use_libcxx, use_libcxx);
-            self.llvm_use_linker.clone_from(&use_linker);
-            self.llvm_allow_old_toolchain = allow_old_toolchain.unwrap_or(false);
-            self.llvm_offload = offload.unwrap_or(false);
-            self.llvm_polly = polly.unwrap_or(false);
-            self.llvm_clang = clang.unwrap_or(false);
-            self.llvm_enable_warnings = enable_warnings.unwrap_or(false);
-            self.llvm_build_config = build_config.clone().unwrap_or(Default::default());
-
-            self.llvm_from_ci = self.parse_download_ci_llvm(download_ci_llvm, self.llvm_assertions);
-
-            if self.llvm_from_ci {
-                let warn = |option: &str| {
-                    println!(
-                        "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
-                    );
-                    println!(
-                        "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
-                    );
-                };
-
-                if static_libstdcpp.is_some() {
-                    warn("static-libstdcpp");
-                }
-
-                if link_shared.is_some() {
-                    warn("link-shared");
-                }
-
-                // FIXME(#129153): instead of all the ad-hoc `download-ci-llvm` checks that follow,
-                // use the `builder-config` present in tarballs since #128822 to compare the local
-                // config to the ones used to build the LLVM artifacts on CI, and only notify users
-                // if they've chosen a different value.
-
-                if libzstd.is_some() {
-                    println!(
-                        "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
-                        like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
-                        artifacts builder config."
-                    );
-                    println!(
-                        "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
-                    );
-                }
-            }
-
-            if !self.llvm_from_ci && self.llvm_thin_lto && link_shared.is_none() {
-                // If we're building with ThinLTO on, by default we want to link
-                // to LLVM shared, to avoid re-doing ThinLTO (which happens in
-                // the link step) with each stage.
-                self.llvm_link_shared.set(Some(true));
-            }
-        } else {
-            self.llvm_from_ci = self.parse_download_ci_llvm(None, false);
-        }
-
-        self.llvm_tests = llvm_tests.unwrap_or(false);
-        self.llvm_enzyme = llvm_enzyme.unwrap_or(false);
-        self.llvm_offload = llvm_offload.unwrap_or(false);
-        self.llvm_plugins = llvm_plugins.unwrap_or(false);
-    }
-}
diff --git a/src/bootstrap/src/core/config/toml/mod.rs b/src/bootstrap/src/core/config/toml/mod.rs
index 01eb243159c..7af22432ef8 100644
--- a/src/bootstrap/src/core/config/toml/mod.rs
+++ b/src/bootstrap/src/core/config/toml/mod.rs
@@ -5,7 +5,7 @@
 //! these raw TOML configurations from various sources (the main `bootstrap.toml`,
 //! included files, profile defaults, and command-line overrides). This processed
 //! TOML data then serves as an intermediate representation, which is further
-//! transformed and applied to the final [`Config`] struct.
+//! transformed and applied to the final `Config` struct.
 
 use serde::Deserialize;
 use serde_derive::Deserialize;
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 03da993a17d..b95fb236fa1 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -1,22 +1,16 @@
 //! This module defines the `Rust` struct, which represents the `[rust]` table
 //! in the `bootstrap.toml` configuration file.
 
-use std::str::FromStr;
-
 use serde::{Deserialize, Deserializer};
 
 use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
 use crate::core::config::toml::TomlConfig;
-use crate::core::config::{
-    DebuginfoLevel, Merge, ReplaceOpt, RustcLto, StringOrBool, set, threads_from_config,
-};
-use crate::flags::Warnings;
-use crate::{
-    BTreeSet, CodegenBackendKind, Config, HashSet, PathBuf, TargetSelection, define_config, exit,
-};
+use crate::core::config::{DebuginfoLevel, Merge, ReplaceOpt, StringOrBool};
+use crate::{BTreeSet, CodegenBackendKind, HashSet, PathBuf, TargetSelection, define_config, exit};
 
 define_config! {
     /// TOML representation of how the Rust build is configured.
+    #[derive(Default)]
     struct Rust {
         optimize: Option<RustOptimize> = "optimize",
         debug: Option<bool> = "debug",
@@ -424,7 +418,7 @@ pub(crate) fn parse_codegen_backends(
 }
 
 #[cfg(not(test))]
-fn default_lld_opt_in_targets() -> Vec<String> {
+pub fn default_lld_opt_in_targets() -> Vec<String> {
     vec!["x86_64-unknown-linux-gnu".to_string()]
 }
 
@@ -434,7 +428,7 @@ thread_local! {
 }
 
 #[cfg(test)]
-fn default_lld_opt_in_targets() -> Vec<String> {
+pub fn default_lld_opt_in_targets() -> Vec<String> {
     TEST_LLD_OPT_IN_TARGETS.with(|cell| cell.borrow().clone()).unwrap_or_default()
 }
 
@@ -447,250 +441,3 @@ pub fn with_lld_opt_in_targets<R>(targets: Vec<String>, f: impl FnOnce() -> R) -
         result
     })
 }
-
-impl Config {
-    pub fn apply_rust_config(&mut self, toml_rust: Option<Rust>, warnings: Warnings) {
-        let mut debug = None;
-        let mut rustc_debug_assertions = None;
-        let mut std_debug_assertions = None;
-        let mut tools_debug_assertions = None;
-        let mut overflow_checks = None;
-        let mut overflow_checks_std = None;
-        let mut debug_logging = None;
-        let mut debuginfo_level = None;
-        let mut debuginfo_level_rustc = None;
-        let mut debuginfo_level_std = None;
-        let mut debuginfo_level_tools = None;
-        let mut debuginfo_level_tests = None;
-        let mut optimize = None;
-        let mut lld_enabled = None;
-        let mut std_features = None;
-
-        if let Some(rust) = toml_rust {
-            let Rust {
-                optimize: optimize_toml,
-                debug: debug_toml,
-                codegen_units,
-                codegen_units_std,
-                rustc_debug_assertions: rustc_debug_assertions_toml,
-                std_debug_assertions: std_debug_assertions_toml,
-                tools_debug_assertions: tools_debug_assertions_toml,
-                overflow_checks: overflow_checks_toml,
-                overflow_checks_std: overflow_checks_std_toml,
-                debug_logging: debug_logging_toml,
-                debuginfo_level: debuginfo_level_toml,
-                debuginfo_level_rustc: debuginfo_level_rustc_toml,
-                debuginfo_level_std: debuginfo_level_std_toml,
-                debuginfo_level_tools: debuginfo_level_tools_toml,
-                debuginfo_level_tests: debuginfo_level_tests_toml,
-                backtrace,
-                incremental,
-                randomize_layout,
-                default_linker,
-                channel: _, // already handled above
-                musl_root,
-                rpath,
-                verbose_tests,
-                optimize_tests,
-                codegen_tests,
-                omit_git_hash: _, // already handled above
-                dist_src,
-                save_toolstates,
-                codegen_backends,
-                lld: lld_enabled_toml,
-                llvm_tools,
-                llvm_bitcode_linker,
-                deny_warnings,
-                backtrace_on_ice,
-                verify_llvm_ir,
-                thin_lto_import_instr_limit,
-                remap_debuginfo,
-                jemalloc,
-                test_compare_mode,
-                llvm_libunwind,
-                control_flow_guard,
-                ehcont_guard,
-                new_symbol_mangling,
-                profile_generate,
-                profile_use,
-                download_rustc,
-                lto,
-                validate_mir_opts,
-                frame_pointers,
-                stack_protector,
-                strip,
-                lld_mode,
-                std_features: std_features_toml,
-            } = rust;
-
-            // FIXME(#133381): alt rustc builds currently do *not* have rustc debug assertions
-            // enabled. We should not download a CI alt rustc if we need rustc to have debug
-            // assertions (e.g. for crashes test suite). This can be changed once something like
-            // [Enable debug assertions on alt
-            // builds](https://github.com/rust-lang/rust/pull/131077) lands.
-            //
-            // Note that `rust.debug = true` currently implies `rust.debug-assertions = true`!
-            //
-            // This relies also on the fact that the global default for `download-rustc` will be
-            // `false` if it's not explicitly set.
-            let debug_assertions_requested = matches!(rustc_debug_assertions_toml, Some(true))
-                || (matches!(debug_toml, Some(true))
-                    && !matches!(rustc_debug_assertions_toml, Some(false)));
-
-            if debug_assertions_requested
-                && let Some(ref opt) = download_rustc
-                && opt.is_string_or_true()
-            {
-                eprintln!(
-                    "WARN: currently no CI rustc builds have rustc debug assertions \
-                            enabled. Please either set `rust.debug-assertions` to `false` if you \
-                            want to use download CI rustc or set `rust.download-rustc` to `false`."
-                );
-            }
-
-            self.download_rustc_commit = self.download_ci_rustc_commit(
-                download_rustc,
-                debug_assertions_requested,
-                self.llvm_assertions,
-            );
-
-            debug = debug_toml;
-            rustc_debug_assertions = rustc_debug_assertions_toml;
-            std_debug_assertions = std_debug_assertions_toml;
-            tools_debug_assertions = tools_debug_assertions_toml;
-            overflow_checks = overflow_checks_toml;
-            overflow_checks_std = overflow_checks_std_toml;
-            debug_logging = debug_logging_toml;
-            debuginfo_level = debuginfo_level_toml;
-            debuginfo_level_rustc = debuginfo_level_rustc_toml;
-            debuginfo_level_std = debuginfo_level_std_toml;
-            debuginfo_level_tools = debuginfo_level_tools_toml;
-            debuginfo_level_tests = debuginfo_level_tests_toml;
-            lld_enabled = lld_enabled_toml;
-            std_features = std_features_toml;
-
-            if optimize_toml.as_ref().is_some_and(|v| matches!(v, RustOptimize::Bool(false))) {
-                eprintln!(
-                    "WARNING: setting `optimize` to `false` is known to cause errors and \
-                    should be considered unsupported. Refer to `bootstrap.example.toml` \
-                    for more details."
-                );
-            }
-
-            optimize = optimize_toml;
-            self.rust_new_symbol_mangling = new_symbol_mangling;
-            set(&mut self.rust_optimize_tests, optimize_tests);
-            set(&mut self.codegen_tests, codegen_tests);
-            set(&mut self.rust_rpath, rpath);
-            set(&mut self.rust_strip, strip);
-            set(&mut self.rust_frame_pointers, frame_pointers);
-            self.rust_stack_protector = stack_protector;
-            set(&mut self.jemalloc, jemalloc);
-            set(&mut self.test_compare_mode, test_compare_mode);
-            set(&mut self.backtrace, backtrace);
-            set(&mut self.rust_dist_src, dist_src);
-            set(&mut self.verbose_tests, verbose_tests);
-            // in the case "false" is set explicitly, do not overwrite the command line args
-            if let Some(true) = incremental {
-                self.incremental = true;
-            }
-            set(&mut self.lld_mode, lld_mode);
-            set(&mut self.llvm_bitcode_linker_enabled, llvm_bitcode_linker);
-
-            self.rust_randomize_layout = randomize_layout.unwrap_or_default();
-            self.llvm_tools_enabled = llvm_tools.unwrap_or(true);
-
-            self.llvm_enzyme = self.channel == "dev" || self.channel == "nightly";
-            self.rustc_default_linker = default_linker;
-            self.musl_root = musl_root.map(PathBuf::from);
-            self.save_toolstates = save_toolstates.map(PathBuf::from);
-            set(
-                &mut self.deny_warnings,
-                match warnings {
-                    Warnings::Deny => Some(true),
-                    Warnings::Warn => Some(false),
-                    Warnings::Default => deny_warnings,
-                },
-            );
-            set(&mut self.backtrace_on_ice, backtrace_on_ice);
-            set(&mut self.rust_verify_llvm_ir, verify_llvm_ir);
-            self.rust_thin_lto_import_instr_limit = thin_lto_import_instr_limit;
-            set(&mut self.rust_remap_debuginfo, remap_debuginfo);
-            set(&mut self.control_flow_guard, control_flow_guard);
-            set(&mut self.ehcont_guard, ehcont_guard);
-            self.llvm_libunwind_default =
-                llvm_libunwind.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
-            set(
-                &mut self.rust_codegen_backends,
-                codegen_backends.map(|backends| parse_codegen_backends(backends, "rust")),
-            );
-
-            self.rust_codegen_units = codegen_units.map(threads_from_config);
-            self.rust_codegen_units_std = codegen_units_std.map(threads_from_config);
-
-            if self.rust_profile_use.is_none() {
-                self.rust_profile_use = profile_use;
-            }
-
-            if self.rust_profile_generate.is_none() {
-                self.rust_profile_generate = profile_generate;
-            }
-
-            self.rust_lto =
-                lto.as_deref().map(|value| RustcLto::from_str(value).unwrap()).unwrap_or_default();
-            self.rust_validate_mir_opts = validate_mir_opts;
-        }
-
-        self.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
-
-        // We make `x86_64-unknown-linux-gnu` use the self-contained linker by default, so we will
-        // build our internal lld and use it as the default linker, by setting the `rust.lld` config
-        // to true by default:
-        // - on the `x86_64-unknown-linux-gnu` target
-        // - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that
-        //   we're also able to build the corresponding lld
-        // - or when using an external llvm that's downloaded from CI, which also contains our prebuilt
-        //   lld
-        // - otherwise, we'd be using an external llvm, and lld would not necessarily available and
-        //   thus, disabled
-        // - similarly, lld will not be built nor used by default when explicitly asked not to, e.g.
-        //   when the config sets `rust.lld = false`
-        if default_lld_opt_in_targets().contains(&self.host_target.triple.to_string())
-            && self.hosts == [self.host_target]
-        {
-            let no_llvm_config = self
-                .target_config
-                .get(&self.host_target)
-                .is_none_or(|target_config| target_config.llvm_config.is_none());
-            let enable_lld = self.llvm_from_ci || no_llvm_config;
-            // Prefer the config setting in case an explicit opt-out is needed.
-            self.lld_enabled = lld_enabled.unwrap_or(enable_lld);
-        } else {
-            set(&mut self.lld_enabled, lld_enabled);
-        }
-
-        let default_std_features = BTreeSet::from([String::from("panic-unwind")]);
-        self.rust_std_features = std_features.unwrap_or(default_std_features);
-
-        let default = debug == Some(true);
-        self.rustc_debug_assertions = rustc_debug_assertions.unwrap_or(default);
-        self.std_debug_assertions = std_debug_assertions.unwrap_or(self.rustc_debug_assertions);
-        self.tools_debug_assertions = tools_debug_assertions.unwrap_or(self.rustc_debug_assertions);
-        self.rust_overflow_checks = overflow_checks.unwrap_or(default);
-        self.rust_overflow_checks_std = overflow_checks_std.unwrap_or(self.rust_overflow_checks);
-
-        self.rust_debug_logging = debug_logging.unwrap_or(self.rustc_debug_assertions);
-
-        let with_defaults = |debuginfo_level_specific: Option<_>| {
-            debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
-                DebuginfoLevel::Limited
-            } else {
-                DebuginfoLevel::None
-            })
-        };
-        self.rust_debuginfo_level_rustc = with_defaults(debuginfo_level_rustc);
-        self.rust_debuginfo_level_std = with_defaults(debuginfo_level_std);
-        self.rust_debuginfo_level_tools = with_defaults(debuginfo_level_tools);
-        self.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(DebuginfoLevel::None);
-    }
-}
diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs
index 9dedadff3a1..2c06fd083a8 100644
--- a/src/bootstrap/src/core/config/toml/target.rs
+++ b/src/bootstrap/src/core/config/toml/target.rs
@@ -7,18 +7,12 @@
 //! * [`TomlTarget`]: This struct directly mirrors the `[target.<triple>]` sections in your
 //!   `bootstrap.toml`. It's used for deserializing raw TOML data for a specific target.
 //! * [`Target`]: This struct represents the processed and validated configuration for a
-//!   build target, which is is stored in the main [`Config`] structure.
-//! * [`Config::apply_target_config`]: This method processes the `TomlTarget` data and
-//!   applies it to the global [`Config`], ensuring proper path resolution, validation,
-//!   and integration with other build settings.
-
-use std::collections::HashMap;
+//!   build target, which is is stored in the main `Config` structure.
 
 use serde::{Deserialize, Deserializer};
 
-use crate::core::config::toml::rust::parse_codegen_backends;
 use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool};
-use crate::{CodegenBackendKind, Config, HashSet, PathBuf, TargetSelection, define_config, exit};
+use crate::{CodegenBackendKind, HashSet, PathBuf, define_config, exit};
 
 define_config! {
     /// TOML representation of how each build target is configured.
@@ -93,68 +87,3 @@ impl Target {
         target
     }
 }
-
-impl Config {
-    pub fn apply_target_config(&mut self, toml_target: Option<HashMap<String, TomlTarget>>) {
-        if let Some(t) = toml_target {
-            for (triple, cfg) in t {
-                let mut target = Target::from_triple(&triple);
-
-                if let Some(ref s) = cfg.llvm_config {
-                    if self.download_rustc_commit.is_some() && triple == *self.host_target.triple {
-                        panic!(
-                            "setting llvm_config for the host is incompatible with download-rustc"
-                        );
-                    }
-                    target.llvm_config = Some(self.src.join(s));
-                }
-                if let Some(patches) = cfg.llvm_has_rust_patches {
-                    assert!(
-                        self.submodules == Some(false) || cfg.llvm_config.is_some(),
-                        "use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
-                    );
-                    target.llvm_has_rust_patches = Some(patches);
-                }
-                if let Some(ref s) = cfg.llvm_filecheck {
-                    target.llvm_filecheck = Some(self.src.join(s));
-                }
-                target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| {
-                    v.parse().unwrap_or_else(|_| {
-                        panic!("failed to parse target.{triple}.llvm-libunwind")
-                    })
-                });
-                if let Some(s) = cfg.no_std {
-                    target.no_std = s;
-                }
-                target.cc = cfg.cc.map(PathBuf::from);
-                target.cxx = cfg.cxx.map(PathBuf::from);
-                target.ar = cfg.ar.map(PathBuf::from);
-                target.ranlib = cfg.ranlib.map(PathBuf::from);
-                target.linker = cfg.linker.map(PathBuf::from);
-                target.crt_static = cfg.crt_static;
-                target.musl_root = cfg.musl_root.map(PathBuf::from);
-                target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
-                target.wasi_root = cfg.wasi_root.map(PathBuf::from);
-                target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
-                target.runner = cfg.runner;
-                target.sanitizers = cfg.sanitizers;
-                target.profiler = cfg.profiler;
-                target.rpath = cfg.rpath;
-                target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
-                target.jemalloc = cfg.jemalloc;
-                if let Some(backends) = cfg.codegen_backends {
-                    target.codegen_backends =
-                        Some(parse_codegen_backends(backends, &format!("target.{triple}")))
-                }
-
-                target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| {
-                    v.parse().unwrap_or_else(|_| {
-                        panic!("invalid value for target.{triple}.split-debuginfo")
-                    })
-                });
-
-                self.target_config.insert(TargetSelection::from_user(&triple), target);
-            }
-        }
-    }
-}
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 15e04f59129..3080e641b5b 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -33,6 +33,7 @@ pub struct Finder {
 //
 // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
 const STAGE0_MISSING_TARGETS: &[&str] = &[
+    "armv7a-vex-v5",
     // just a dummy comment so the list doesn't get onelined
 ];
 
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index e49513a2116..4abf386e5de 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -517,7 +517,7 @@ impl Build {
             local_rebuild: config.local_rebuild,
             fail_fast: config.cmd.fail_fast(),
             doc_tests: config.cmd.doc_tests(),
-            verbosity: config.verbose,
+            verbosity: config.exec_ctx.verbosity as usize,
 
             host_target: config.host_target,
             hosts: config.hosts.clone(),
@@ -1105,17 +1105,6 @@ impl Build {
         self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into())
     }
 
-    #[must_use = "Groups should not be dropped until the Step finishes running"]
-    #[track_caller]
-    fn msg_build(
-        &self,
-        compiler: Compiler,
-        what: impl Display,
-        target: impl Into<Option<TargetSelection>>,
-    ) -> Option<gha::Group> {
-        self.msg(Kind::Build, compiler.stage, what, compiler.host, target)
-    }
-
     /// Return a `Group` guard for a [`Step`] that is built for each `--stage`.
     ///
     /// [`Step`]: crate::core::builder::Step
@@ -1162,20 +1151,21 @@ impl Build {
 
     #[must_use = "Groups should not be dropped until the Step finishes running"]
     #[track_caller]
-    fn msg_sysroot_tool(
+    fn msg_rustc_tool(
         &self,
         action: impl Into<Kind>,
-        stage: u32,
+        build_stage: u32,
         what: impl Display,
         host: TargetSelection,
         target: TargetSelection,
     ) -> Option<gha::Group> {
         let action = action.into().description();
         let msg = |fmt| format!("{action} {what} {fmt}");
+
         let msg = if host == target {
-            msg(format_args!("(stage{stage} -> stage{}, {target})", stage + 1))
+            msg(format_args!("(stage{build_stage} -> stage{}, {target})", build_stage + 1))
         } else {
-            msg(format_args!("(stage{stage}:{host} -> stage{}:{target})", stage + 1))
+            msg(format_args!("(stage{build_stage}:{host} -> stage{}:{target})", build_stage + 1))
         };
         self.group(&msg)
     }
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 209ff393973..7527dff9cd8 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -550,7 +550,7 @@ impl Default for CommandOutput {
 #[derive(Clone, Default)]
 pub struct ExecutionContext {
     dry_run: DryRun,
-    verbose: u8,
+    pub verbosity: u8,
     pub fail_fast: bool,
     delayed_failures: Arc<Mutex<Vec<String>>>,
     command_cache: Arc<CommandCache>,
@@ -603,8 +603,8 @@ impl CommandCache {
 }
 
 impl ExecutionContext {
-    pub fn new() -> Self {
-        ExecutionContext::default()
+    pub fn new(verbosity: u8, fail_fast: bool) -> Self {
+        Self { verbosity, fail_fast, ..Default::default() }
     }
 
     pub fn dry_run(&self) -> bool {
@@ -629,7 +629,7 @@ impl ExecutionContext {
     }
 
     pub fn is_verbose(&self) -> bool {
-        self.verbose > 0
+        self.verbosity > 0
     }
 
     pub fn fail_fast(&self) -> bool {
@@ -640,8 +640,8 @@ impl ExecutionContext {
         self.dry_run = value;
     }
 
-    pub fn set_verbose(&mut self, value: u8) {
-        self.verbose = value;
+    pub fn set_verbosity(&mut self, value: u8) {
+        self.verbosity = value;
     }
 
     pub fn set_fail_fast(&mut self, value: bool) {
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index eb00ed566c2..451482717b6 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -404,9 +404,8 @@ pub fn linker_args(
     builder: &Builder<'_>,
     target: TargetSelection,
     lld_threads: LldThreads,
-    stage: u32,
 ) -> Vec<String> {
-    let mut args = linker_flags(builder, target, lld_threads, stage);
+    let mut args = linker_flags(builder, target, lld_threads);
 
     if let Some(linker) = builder.linker(target) {
         args.push(format!("-Clinker={}", linker.display()));
@@ -421,29 +420,16 @@ pub fn linker_flags(
     builder: &Builder<'_>,
     target: TargetSelection,
     lld_threads: LldThreads,
-    stage: u32,
 ) -> Vec<String> {
     let mut args = vec![];
     if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
         match builder.config.lld_mode {
             LldMode::External => {
-                // cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
-                // `-Clinker-features` has been stabilized.
-                if stage == 0 {
-                    args.push("-Zlinker-features=+lld".to_string());
-                } else {
-                    args.push("-Clinker-features=+lld".to_string());
-                }
+                args.push("-Clinker-features=+lld".to_string());
                 args.push("-Zunstable-options".to_string());
             }
             LldMode::SelfContained => {
-                // cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
-                // `-Clinker-features` has been stabilized.
-                if stage == 0 {
-                    args.push("-Zlinker-features=+lld".to_string());
-                } else {
-                    args.push("-Clinker-features=+lld".to_string());
-                }
+                args.push("-Clinker-features=+lld".to_string());
                 args.push("-Clink-self-contained=+linker".to_string());
                 args.push("-Zunstable-options".to_string());
             }
@@ -465,9 +451,8 @@ pub fn add_rustdoc_cargo_linker_args(
     builder: &Builder<'_>,
     target: TargetSelection,
     lld_threads: LldThreads,
-    stage: u32,
 ) {
-    let args = linker_args(builder, target, lld_threads, stage);
+    let args = linker_args(builder, target, lld_threads);
     let mut flags = cmd
         .get_envs()
         .find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None })
diff --git a/src/ci/docker/scripts/build-clang.sh b/src/ci/docker/scripts/build-clang.sh
index 536991cc06b..905c4077304 100755
--- a/src/ci/docker/scripts/build-clang.sh
+++ b/src/ci/docker/scripts/build-clang.sh
@@ -5,7 +5,7 @@ set -ex
 source shared.sh
 
 # Try to keep the LLVM version here in sync with src/ci/scripts/install-clang.sh
-LLVM=llvmorg-20.1.0-rc2
+LLVM=llvmorg-21.1.0-rc2
 
 mkdir llvm-project
 cd llvm-project
@@ -44,8 +44,10 @@ hide_output \
       -DLLVM_INCLUDE_BENCHMARKS=OFF \
       -DLLVM_INCLUDE_TESTS=OFF \
       -DLLVM_INCLUDE_EXAMPLES=OFF \
-      -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt;bolt" \
+      -DLLVM_ENABLE_PROJECTS="clang;lld;bolt" \
+      -DLLVM_ENABLE_RUNTIMES="compiler-rt" \
       -DLLVM_BINUTILS_INCDIR="/rustroot/lib/gcc/$GCC_PLUGIN_TARGET/$GCC_VERSION/plugin/include/" \
+      -DRUNTIMES_CMAKE_ARGS="-DCMAKE_CXX_FLAGS=\"--gcc-toolchain=/rustroot\"" \
       -DC_INCLUDE_DIRS="$INC"
 
 hide_output make -j$(nproc)
diff --git a/src/doc/book b/src/doc/book
-Subproject b2d1a0821e12a676b496d61891b8e3d374a8e83
+Subproject 3e9dc46aa563ca0c53ec826c41b05f10c591592
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 1f45bd41fa6c17b7c048ed6bfe5f168c4311206
+Subproject 1be151c051a082b542548c62cafbcb055fa8944
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject e386be5f44af711854207c11fdd61bb576270b0
+Subproject bd1279cdc9865bfff605e741fb76a0b2f07314a
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index e9f1626f1fd..6ec700b9b4d 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-383b9c447b61641e1f1a3850253944a897a60827
+6bcdcc73bd11568fd85f5a38b58e1eda054ad1cd
diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md
index 1e792de3c8c..b376e962ff6 100644
--- a/src/doc/rustc-dev-guide/src/offload/installation.md
+++ b/src/doc/rustc-dev-guide/src/offload/installation.md
@@ -8,7 +8,7 @@ First you need to clone and configure the Rust repository:
 ```bash
 git clone git@github.com:rust-lang/rust
 cd rust
-./configure --enable-llvm-link-shared --release-channel=nightly --enable-llvm-assertions --enable-offload --enable-enzyme --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
+./configure --enable-llvm-link-shared --release-channel=nightly --enable-llvm-assertions --enable-llvm-offload --enable-llvm-enzyme --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
 ```
 
 Afterwards you can build rustc using:
diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md
index 12b76828b5c..378d8c4453f 100644
--- a/src/doc/rustc-dev-guide/src/overview.md
+++ b/src/doc/rustc-dev-guide/src/overview.md
@@ -321,6 +321,10 @@ the name `'tcx`, which means that something is tied to the lifetime of the
 
 [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
 
+For more information about queries in the compiler, see [the queries chapter][queries].
+
+[queries]: ./query.md
+
 ### `ty::Ty`
 
 Types are really important in Rust, and they form the core of a lot of compiler
diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md
index d0cee54adb6..c26d34273d7 100644
--- a/src/doc/rustc-dev-guide/src/stability.md
+++ b/src/doc/rustc-dev-guide/src/stability.md
@@ -181,4 +181,7 @@ the `deprecated_in_future` lint is triggered which is default `allow`, but most
 of the standard library raises it to a warning with
 `#![warn(deprecated_in_future)]`.
 
+## unstable_feature_bound
+The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. Currently, only `impl`s and free functions can be annotated with `#[unstable_feature_bound]`.
+
 [blog]: https://www.ralfj.de/blog/2018/07/19/const.html
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index f6e313062cd..317b65f98cd 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -342,7 +342,6 @@ coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 > **TODO**
 >
 > - Is there any support for using an iOS emulator?
-> - It's also unclear to me how the wasm or asm.js tests are run.
 
 [armhf-gnu]: https://github.com/rust-lang/rust/tree/master/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
 [QEMU]: https://www.qemu.org/
@@ -350,6 +349,28 @@ coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 [remote-test-server]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
 [src/bootstrap/src/core/build_steps/test.rs]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/test.rs
 
+## Testing tests on wasi (wasm32-wasip1)
+
+Some tests are specific to wasm targets.
+To run theste tests, you have to pass `--target wasm32-wasip1` to `x test`.
+Additionally, you need the wasi sdk.
+Follow the install instructions from the [wasi sdk repository] to get a sysroot on your computer.
+On the [wasm32-wasip1 target support page] a minimum version is specified that your sdk must be able to build.
+Some cmake commands that take a while and give a lot of very concerning c++ warnings...
+Then, in `bootstrap.toml`, point to the sysroot like so:
+
+```
+[target.wasm32-wasip1]
+wasi-root = "<wasi-sdk location>/build/sysroot/install/share/wasi-sysroot"
+```
+
+In my case I git-cloned it next to my rust folder, so it was `../wasi-sdk/build/....`
+Now, tests should just run, you don't have to set up anything else.
+
+[wasi sdk repository]: https://github.com/WebAssembly/wasi-sdk
+[wasm32-wasip1 target support page]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support/wasm32-wasip1.md#building-the-target.
+
+
 ## Running rustc_codegen_gcc tests
 
 First thing to know is that it only supports linux x86_64 at the moment. We will
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 7c688e32bc0..25f154f1180 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -65,6 +65,7 @@
     - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
     - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
+    - [armv7a-vex-v5](platform-support/armv7a-vex-v5.md)
     - [\*-android and \*-androideabi](platform-support/android.md)
     - [\*-linux-ohos](platform-support/openharmony.md)
     - [\*-hurd-gnu](platform-support/hurd.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 65b70630153..8ebaa8dd874 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -297,6 +297,7 @@ target | std | host | notes
 [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3
 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3, hardfloat
 [`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * |  | Bare Armv7-A, hardfloat
+[`armv7a-vex-v5`](platform-support/armv7a-vex-v5.md) | ? |  | Armv7-A Cortex-A9 VEX V5 Brain, VEXos
 [`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ |  | Armv7-A Apple WatchOS
 [`armv7s-apple-ios`](platform-support/apple-ios.md) | ✓ |  | Armv7-A Apple-A6 Apple iOS
 [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * |  | Bare Armv8-R, hardfloat
diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
index d4b71dbd4f4..c6f68f7a1e8 100644
--- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md
+++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
@@ -56,6 +56,17 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios-macabi your-code.rs
 ```
 
+The target can be differentiated from the iOS targets with the
+`target_env = "macabi"` cfg (or `target_abi = "macabi"` before Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(target_env = "macabi") {
+    // Do something only on Mac Catalyst.
+}
+```
+
+This is similar to the `TARGET_OS_MACCATALYST` define in C code.
+
 ## Testing
 
 Mac Catalyst binaries can be run directly on macOS 10.15 Catalina or newer.
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index 64325554ab6..586afa65226 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -66,6 +66,20 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios your-code.rs
 ```
 
+The simulator variants can be differentiated from the variants running
+on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before
+Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(all(target_vendor = "apple", target_env = "sim")) {
+    // Do something on the iOS/tvOS/visionOS/watchOS Simulator.
+} {
+    // Everything else, like Windows and non-Simulator iOS.
+}
+```
+
+This is similar to the `TARGET_OS_SIMULATOR` define in C code.
+
 ## Testing
 
 There is no support for running the Rust or standard library testsuite at the
diff --git a/src/doc/rustc/src/platform-support/armv7a-vex-v5.md b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md
new file mode 100644
index 00000000000..a7da1b16f7e
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md
@@ -0,0 +1,83 @@
+# `armv7a-vex-v5`
+
+**Tier: 3**
+
+Allows compiling user programs for the [VEX V5 Brain](https://www.vexrobotics.com/276-4810.html), a microcontroller for educational and competitive robotics.
+
+Rust support for this target is not affiliated with VEX Robotics or IFI.
+
+## Target maintainers
+
+This target is maintained by members of the [vexide](https://github.com/vexide) organization:
+
+- [@lewisfm](https://github.com/lewisfm)
+- [@Tropix126](https://github.com/Tropix126)
+- [@Gavin-Niederman](https://github.com/Gavin-Niederman)
+- [@max-niederman](https://github.com/max-niederman)
+
+## Requirements
+
+This target is cross-compiled and currently requires `#![no_std]`. Dynamic linking is unsupported.
+
+When compiling for this target, the "C" calling convention maps to AAPCS with VFP registers (hard float ABI) and the "system" calling convention maps to AAPCS without VFP registers (soft float ABI).
+
+This target generates binaries in the ELF format that may uploaded to the brain with external tools.
+
+## Building the target
+
+You can build Rust with support for this target by adding it to the `target` list in `bootstrap.toml`, and then running `./x build --target armv7a-vex-v5 compiler`.
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+When the compiler builds a binary, an ELF build artifact will be produced. Additional tools are required for this artifact to be recognizable to VEXos as a user program.
+
+The [cargo-v5](https://github.com/vexide/cargo-v5) tool is capable of creating binaries that can be uploaded to the V5 brain. This tool wraps the `cargo build` command by supplying arguments necessary to build the target and produce an artifact recognizable to VEXos, while also providing functionality for uploading over USB to a V5 Controller or Brain.
+
+To install the tool, run:
+
+```sh
+cargo install cargo-v5
+```
+
+The following fields in your project's `Cargo.toml` are read by `cargo-v5` to configure upload behavior:
+
+```toml
+[package.metadata.v5]
+# Slot number to upload the user program to. This should be from 1-8.
+slot = 1
+# Program icon/thumbnail that will be displayed on the dashboard.
+icon = "cool-x"
+# Use gzip compression when uploading binaries.
+compress = true
+```
+
+To build an uploadable BIN file using the release profile, run:
+
+```sh
+cargo v5 build --release
+```
+
+Programs can also be directly uploaded to the brain over a USB connection immediately after building:
+
+```sh
+cargo v5 upload --release
+```
+
+## Testing
+
+Binaries built for this target can be run in an emulator (such as [vex-v5-qemu](https://github.com/vexide/vex-v5-qemu)), or uploaded to a physical device over a serial (USB) connection.
+
+The default Rust test runner is not supported.
+
+The Rust test suite for `library/std` is not yet supported.
+
+## Cross-compilation toolchains and C code
+
+This target can be cross-compiled from any host.
+
+Linking to C libraries is not supported.
diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md
index 106ec562bfc..36598982481 100644
--- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md
+++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md
@@ -10,6 +10,46 @@ platform.
 [@RDambrosio016](https://github.com/RDambrosio016)
 [@kjetilkjeka](https://github.com/kjetilkjeka)
 
+## Requirements
+
+This target is `no_std` and will typically be built with crate-type `cdylib` and `-C linker-flavor=llbc`, which generates PTX.
+The necessary components for this workflow are:
+
+- `rustup toolchain add nightly`
+- `rustup component add llvm-tools --toolchain nightly`
+- `rustup component add llvm-bitcode-linker --toolchain nightly`
+
+There are two options for using the core library:
+
+- `rustup component add rust-src --toolchain nightly` and build using `-Z build-std=core`.
+- `rustup target add nvptx64-nvidia-cuda --toolchain nightly`
+
+### Target and features
+
+It is generally necessary to specify the target, such as `-C target-cpu=sm_89`, because the default is very old. This implies two target features: `sm_89` and `ptx78` (and all preceding features within `sm_*` and `ptx*`). Rust will default to using the oldest PTX version that supports the target processor (see [this table](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#release-notes-ptx-release-history)), which maximizes driver compatibility.
+One can use `-C target-feature=+ptx80` to choose a later PTX version without changing the target (the default in this case, `ptx78`, requires CUDA driver version 11.8, while `ptx80` would require driver version 12.0).
+Later PTX versions may allow more efficient code generation.
+
+Although Rust follows LLVM in representing `ptx*` and `sm_*` as target features, they should be thought of as having crate granularity, set via (either via `-Ctarget-cpu` and optionally `-Ctarget-feature`).
+While the compiler accepts `#[target_feature(enable = "ptx80", enable = "sm_89")]`, it is not supported, may not behave as intended, and may become erroneous in the future.
+
+## Building Rust kernels
+
+A `no_std` crate containing one or more functions with `extern "ptx-kernel"` can be compiled to PTX using a command like the following.
+
+```console
+$ RUSTFLAGS='-Ctarget-cpu=sm_89' cargo +nightly rustc --target=nvptx64-nvidia-cuda -Zbuild-std=core --crate-type=cdylib -- -Clinker-flavor=llbc -Zunstable-options
+```
+
+Intrinsics in `core::arch::nvptx` may use `#[cfg(target_feature = "...")]`, thus it's necessary to use `-Zbuild-std=core` with appropriate `RUSTFLAGS`. The following components are needed for this workflow:
+
+```console
+$ rustup component add rust-src --toolchain nightly
+$ rustup component add llvm-tools --toolchain nightly
+$ rustup component add llvm-bitcode-linker --toolchain nightly
+```
+
+
 <!-- FIXME: fill this out
 
 ## Requirements
diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md
index 87a9a00b3c0..693a0a58b49 100644
--- a/src/doc/unstable-book/src/compiler-flags/coverage-options.md
+++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md
@@ -5,7 +5,7 @@ This option controls details of the coverage instrumentation performed by
 
 Multiple options can be passed, separated by commas. Valid options are:
 
-- `block`, `branch`, `condition`, `mcdc`:
+- `block`, `branch`, `condition`:
   Sets the level of coverage instrumentation.
   Setting the level will override any previously-specified level.
   - `block` (default):
@@ -15,6 +15,3 @@ Multiple options can be passed, separated by commas. Valid options are:
   - `condition`:
     In addition to branch coverage, also instruments some boolean expressions
     as branches, even if they are not directly used as branch conditions.
-  - `mcdc`:
-    In addition to condition coverage, also enables MC/DC instrumentation.
-    (Branch coverage instrumentation may differ in some cases.)
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 782311e593b..26b087feb16 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -480,10 +480,28 @@ impl Item {
         }
     }
 
+    /// If the item has doc comments from a reexport, returns the item id of that reexport,
+    /// otherwise returns returns the item id.
+    ///
+    /// This is used as a key for caching intra-doc link resolution,
+    /// to prevent two reexports of the same item from using the same cache.
+    pub(crate) fn item_or_reexport_id(&self) -> ItemId {
+        // added documentation on a reexport is always prepended.
+        self.attrs
+            .doc_strings
+            .first()
+            .map(|x| x.item_id)
+            .flatten()
+            .map(ItemId::from)
+            .unwrap_or(self.item_id)
+    }
+
     pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
         use crate::html::format::{href, link_tooltip};
 
-        let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
+        let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
+            return vec![];
+        };
         links
             .iter()
             .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index fed4296fa22..c52c7236883 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -804,8 +804,7 @@ impl Options {
 
         let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
         let with_examples = matches.opt_strs("with-examples");
-        let call_locations =
-            crate::scrape_examples::load_call_locations(with_examples, dcx, &mut loaded_paths);
+        let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
         let doctest_build_args = matches.opt_strs("doctest-build-arg");
 
         let unstable_features =
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 99b3da8b2cd..c48863b4681 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1838,6 +1838,10 @@ instead, we check that it's not a "finger" cursor.
 	border-right: 3px solid var(--target-border-color);
 }
 
+a.tooltip {
+	font-family: var(--font-family);
+}
+
 .code-header a.tooltip {
 	color: inherit;
 	margin-right: 15px;
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index c9fa3a4837f..bcb676cd1f1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1082,7 +1082,12 @@ impl LinkCollector<'_, '_> {
             for md_link in preprocessed_markdown_links(&doc) {
                 let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
                 if let Some(link) = link {
-                    self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
+                    self.cx
+                        .cache
+                        .intra_doc_links
+                        .entry(item.item_or_reexport_id())
+                        .or_default()
+                        .insert(link);
                 }
             }
         }
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 4d29c74e1eb..9f71d6ae789 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -333,11 +333,14 @@ pub(crate) fn run(
 pub(crate) fn load_call_locations(
     with_examples: Vec<String>,
     dcx: DiagCtxtHandle<'_>,
-    loaded_paths: &mut Vec<PathBuf>,
 ) -> AllCallLocations {
     let mut all_calls: AllCallLocations = FxIndexMap::default();
     for path in with_examples {
-        loaded_paths.push(path.clone().into());
+        // FIXME: Figure out why this line is causing this feature to crash in specific contexts.
+        // Full issue backlog is available here: <https://github.com/rust-lang/rust/pull/144600>.
+        //
+        // Can be checked with `tests/run-make/rustdoc-scrape-examples-paths`.
+        // loaded_paths.push(path.clone().into());
         let bytes = match fs::read(&path) {
             Ok(bytes) => bytes,
             Err(e) => dcx.fatal(format!("failed to load examples: {e}")),
diff --git a/src/llvm-project b/src/llvm-project
-Subproject e8a2ffcf322f45b8dce82c65ab27a3e2430a6b5
+Subproject d35840afa50d2615835d6a836f1967c57008188
diff --git a/src/stage0 b/src/stage0
index 3313edf329c..73bf5ba4b78 100644
--- a/src/stage0
+++ b/src/stage0
@@ -13,486 +13,506 @@ nightly_branch=master
 # All changes below this comment will be overridden the next time the
 # tool is executed.
 
-compiler_date=2025-06-24
+compiler_date=2025-08-05
 compiler_version=beta
-rustfmt_date=2025-06-24
+rustfmt_date=2025-08-06
 rustfmt_version=nightly
 
-dist/2025-06-24/rustc-beta-aarch64-apple-darwin.tar.gz=d52ba1003d317f779490731ac66bcf4ebeda0e56648ac35373c6f7385515c06d
-dist/2025-06-24/rustc-beta-aarch64-apple-darwin.tar.xz=1d4ab402eded5cfe91040f3af5128448cc4b57ceb53b82571bde8a86f42681df
-dist/2025-06-24/rustc-beta-aarch64-pc-windows-msvc.tar.gz=aa82360f0428aa3c918c9fb1b0f41752655aae5249f5795d34b1a4737362cf8d
-dist/2025-06-24/rustc-beta-aarch64-pc-windows-msvc.tar.xz=969a5aa9d69a2e64c918d1757489f2532544754563aae73aea9bde7d85d22d2f
-dist/2025-06-24/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=bac05a8267c6dd563ae0869cdfaac9fa3a07e9d64c5c332bc4028f7f3e8ba668
-dist/2025-06-24/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=3d37128f78af2b6fffb661dc05c2f7ace3a8307b3d60176fcc2b70bd4d802b90
-dist/2025-06-24/rustc-beta-aarch64-unknown-linux-musl.tar.gz=268f550fb51c63f0e8ad8c8a955633c79dde3011c26c1f3b555f2575a8366f88
-dist/2025-06-24/rustc-beta-aarch64-unknown-linux-musl.tar.xz=b706d4cdb5b4e86602994c74476b4be7ff94749c3104553ba6d73356cb914582
-dist/2025-06-24/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=20b0e77b39b9ef5c80f19a3b6daec5e479cf3e0af8b623cee81d38f0a5318cfc
-dist/2025-06-24/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0add4728a9a993c6b33d8cda11c27520e013f0721532686b5919d3958d2333f0
-dist/2025-06-24/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=4bdd3e99737137d3595fa9e27e590d8589d5f380e9e634fdd65e8c526f872fed
-dist/2025-06-24/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=662c73cf5f9e0796be7d8ad19a064b5bbbace7b8d1e55644acc19880fa76526c
-dist/2025-06-24/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=c31b823567177bba812b1074af46282083214314ba3e0c4c2386748526fb64d0
-dist/2025-06-24/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=67eed549762b32d50117e200b5157a60388e67d246b60ddf8fc4e41defa3ed0e
-dist/2025-06-24/rustc-beta-i686-pc-windows-gnu.tar.gz=de5c004abce01c43ac7caaefa9ed10006e41b83d085bcbe6fceb4040138787ca
-dist/2025-06-24/rustc-beta-i686-pc-windows-gnu.tar.xz=f5b715035c76cae7099c74e0f00e924c2cf965aa7152518c2e6313ef04d81d8c
-dist/2025-06-24/rustc-beta-i686-pc-windows-msvc.tar.gz=48a97523dbc061b2a3a575a34b2ba87c0dfca2e56fee67260001ba51c3b37ac1
-dist/2025-06-24/rustc-beta-i686-pc-windows-msvc.tar.xz=5c2254445c7d5cdf3e64c86b29046699fe7f8a6828dcd3f2931aa26d026d71af
-dist/2025-06-24/rustc-beta-i686-unknown-linux-gnu.tar.gz=4515aa57b3f9191fb14d228bedee72044d2fda3e3166780e622d857460c77c57
-dist/2025-06-24/rustc-beta-i686-unknown-linux-gnu.tar.xz=8791d2c9321b36d64280902e0ec04b85728715bdd072f859fbe3d533209504de
-dist/2025-06-24/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=08b9941535edae23971a42803bc398bd87c353dda837ecc68e534be6604d7e35
-dist/2025-06-24/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=a2a109408ba5db4540ad7bbd1e67a9623aae96203c0238aca5fb3c3741ead97f
-dist/2025-06-24/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=41709a32ceb106a618aedcebb1470e6bb3734362790d1aad7d0f59e25c9f76ca
-dist/2025-06-24/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=67294e9465728d7a2e1f9553927067fbba176c1d806a59472b84a2dc18e46032
-dist/2025-06-24/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=a18de5c31855d7a2f73a242217c628a49fe9a64b1374d6720e37e3eb0a584fae
-dist/2025-06-24/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=7785929842939af15a8404f666c95e5786ca0941f1c15dc084f26a5124411e2c
-dist/2025-06-24/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=35e4e2c48895480d5c012d2741a1b3387c1ffb4c4d2440649c0eda182f27f6c1
-dist/2025-06-24/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=3cd480374907eb3816c8db73973abc676c96bc9598943dc89056eb5542d6b6b8
-dist/2025-06-24/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=3901ff91a71c32808f23d715b9e04ce65dfac20746cad1b00c1a964220284cb5
-dist/2025-06-24/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=c670f5201c14464d9e13da1922609369e784a1e482162cf3e9ed281fce926b01
-dist/2025-06-24/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=72f5c00badcc4a87e237b831262d12e94edb960d65f411557a54dc9bf587464b
-dist/2025-06-24/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=337f222313427704cfa4b9f68c89f82e3855f2b3d1cec1c151778fd631674452
-dist/2025-06-24/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=b2a49ff470ce80e887f2eb3b69b39cd65b64a2a25b5f09df91a9e58762a6a159
-dist/2025-06-24/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=1c2b2090ab6ec51df85e6495389adceca4fd414a709d2219fd7b39d1c47c7a49
-dist/2025-06-24/rustc-beta-s390x-unknown-linux-gnu.tar.gz=26ad57058ddb3ad1795300bff0bbbfc1bb3a0437638112655dbec279db78bb11
-dist/2025-06-24/rustc-beta-s390x-unknown-linux-gnu.tar.xz=742c09735a0b50acea601dfd2ae41e931cbb44d7700d6cba18df9e0ccb45bad8
-dist/2025-06-24/rustc-beta-sparcv9-sun-solaris.tar.gz=cc6c4e7bada6d864177a163f1d6b1f75e1e388abe1fcd4de87c2aeb8e609587a
-dist/2025-06-24/rustc-beta-sparcv9-sun-solaris.tar.xz=1fcf41f42ef399bb8c450f6a8c9cef8af960d6fa82495c53273419bd3cbb79a0
-dist/2025-06-24/rustc-beta-x86_64-apple-darwin.tar.gz=b1dd64d9ee00d14a4cf41556b70330606c793a81725494e4f14215092ded4d73
-dist/2025-06-24/rustc-beta-x86_64-apple-darwin.tar.xz=75de284a6a29a453e1e453d372affb5717434584445019582a50d169b7770d65
-dist/2025-06-24/rustc-beta-x86_64-pc-solaris.tar.gz=ff4832c37c0bfb55e54bd02f40251a4d43ab68f41d22ee54543fe37e33561925
-dist/2025-06-24/rustc-beta-x86_64-pc-solaris.tar.xz=e297337e331fab37350f0826328ef1086e210068cc764567905a4caae3f18d0d
-dist/2025-06-24/rustc-beta-x86_64-pc-windows-gnu.tar.gz=fd4dc0fb13dd1cc8ad58f143ff83a8a52fe31e277c6fd19dcf4d51dd5d004135
-dist/2025-06-24/rustc-beta-x86_64-pc-windows-gnu.tar.xz=347de9b9f7ce028fe479803dd846d13be8db6d0baf81a0a4eeb3511cfebe4821
-dist/2025-06-24/rustc-beta-x86_64-pc-windows-msvc.tar.gz=c84ee0f00b5f13fee3ce8c45301577a42866493aefa5460f3385d03398204acd
-dist/2025-06-24/rustc-beta-x86_64-pc-windows-msvc.tar.xz=4b6a27561bc94afe072b66c5bed3f30da712bdc812ff1609feb669556dc878ca
-dist/2025-06-24/rustc-beta-x86_64-unknown-freebsd.tar.gz=493c5c391e7829c8925bc447457c56617076ed32d3ee1465639fa02cda5717d4
-dist/2025-06-24/rustc-beta-x86_64-unknown-freebsd.tar.xz=71e9e3a1d1f5e8dc98403c2a6695c969908ba0cde594c4e20249fe81b67d62d1
-dist/2025-06-24/rustc-beta-x86_64-unknown-illumos.tar.gz=40e58bcfc116546268f5007e4092eeb43c3a582e7090f0bff29fb0ad24a0bc72
-dist/2025-06-24/rustc-beta-x86_64-unknown-illumos.tar.xz=e313e1b0136be269ff68b4d2a71d0414357df66e1ed192e9a60e908c6c64c37f
-dist/2025-06-24/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=0725845044e9ecb37ff6b4c1a030a6c8bf287706601b29ba7fb5284f67d29ba4
-dist/2025-06-24/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=4fdc2e7a65b3924d1577229fe02975a4618481aac35053426abd2b9ede18afde
-dist/2025-06-24/rustc-beta-x86_64-unknown-linux-musl.tar.gz=26426288117d71c8212aa30fa5b874e3aca9e4e706852f18d22da05bbd638dab
-dist/2025-06-24/rustc-beta-x86_64-unknown-linux-musl.tar.xz=bca55f330ec76ebdd6f6dc8764cfb31aa9158cb96758779f8eefc031d393e263
-dist/2025-06-24/rustc-beta-x86_64-unknown-netbsd.tar.gz=007e38bc7d09c4ca3a7ea389ed112a2de0e09f6688e5e1f161a4d11e41d43ab0
-dist/2025-06-24/rustc-beta-x86_64-unknown-netbsd.tar.xz=08a5d9cac358f115af3d0985439e2ff0c79b70b592f99fb3d31b65cb7f56d958
-dist/2025-06-24/rust-std-beta-aarch64-apple-darwin.tar.gz=2c38b17116d9a2d2020e7e84bbaad3b614e8a0c27fe26987416bd183138596ba
-dist/2025-06-24/rust-std-beta-aarch64-apple-darwin.tar.xz=c51b0e3932226017dfb70e8fbd879e9eefd65d5f17ad07db606ebe2ba1500dd0
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios.tar.gz=f71b8bc726eb5f60bb1603607609a1c04569581875d697fb1026b8454ff0b403
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios.tar.xz=ea0634039755708291275ee3af545982f3c29381b1e9675cb087ede59e03b461
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=c457134ea13cdbaf1af7f11148074ac01e6e19415b591a8ee6958ea5006f4754
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=cff6edde276467a7e3674506c9b668abf0004a12464fb22fd35f56537b0dc4b3
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios-sim.tar.gz=c70fcec2f7610058c5cde51847879415376fedfae10ec49a7b198e5c5582aac5
-dist/2025-06-24/rust-std-beta-aarch64-apple-ios-sim.tar.xz=6e763366bfb635915ae7d505c35df55ebf8a1d5373bd5403584d7dd7ac682f21
-dist/2025-06-24/rust-std-beta-aarch64-linux-android.tar.gz=c4d13dcea814eb20b4c7045e6d881df185f6ee1539b42428348068d752718498
-dist/2025-06-24/rust-std-beta-aarch64-linux-android.tar.xz=67d3cc8f90712e50909aca5e734211baeab3ccd47a3cd00dea07839f16770a19
-dist/2025-06-24/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=d882aeee9217327a650ad37b902380c87dd3d02d0d49015cb3052537da42b380
-dist/2025-06-24/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=4aaee0fdc8aad773eb8576c869b111dbfa4e3882cf5cf50da174e63528db01c6
-dist/2025-06-24/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=56b70c5445d95471651093ebe31a16fef54ec91b2acef533f3c1f06c2f18f924
-dist/2025-06-24/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=d60d4aea6fc5345bd0478c92a81bca7ec3589775ec67733aca845d78b9364e8c
-dist/2025-06-24/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=b6946f0c1d01d370d217e3512505211ca4aff4f07c1f7c55d99065b70c9d52fb
-dist/2025-06-24/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=e3479f792c61b425459c691169d8fe55a149dd6c0440aea4a0d9be41d6806b00
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=47c5e35cf704a1496a5d01143d2f418880a4540bbd6b4fd41e4f9988a71ded83
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=010bae09b5a25a7b1b0c1a10dc67f5d7db89212fa9ef7149cea4e4f586d5f252
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=2dba8ca097a3afbc9d51b75c8338f3536b079fa751dbd4a877d89a36cb0e616b
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=9ae1856c909ba57b3c5638e8546fec2e2741a54f5f5b14c73c1c031f33096815
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f0f25e623f96ea98d004039add0232abd5ba7216ba347db3a827d4ec323d3ab1
-dist/2025-06-24/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fcfec16c209afc3362f710d0207e5ff8a596ba7ad7123335ad3670294d0b4e6f
-dist/2025-06-24/rust-std-beta-aarch64-unknown-none.tar.gz=00d63ef3e735db06d0989601a78a21dcbfa4c62bc1ab063a53c48f94ec24b92d
-dist/2025-06-24/rust-std-beta-aarch64-unknown-none.tar.xz=50934b2bec9bfff0c58e9a70adeafa7875236814e8338cc01fab3373822e8d5a
-dist/2025-06-24/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=211e95246719c6242dc243559175bc0d8154c4878b8ca72e4acb6f29c60aca8c
-dist/2025-06-24/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=ba53e4fae39fa980c6eeb1a2d2299eb53ded22dcdfc0390938bdd7b9563ed9eb
-dist/2025-06-24/rust-std-beta-aarch64-unknown-uefi.tar.gz=93e56e090c416f038faca4837c4fb72894f3d6d1a3ba8b9fe27b2ca032deedb6
-dist/2025-06-24/rust-std-beta-aarch64-unknown-uefi.tar.xz=f0f0aebb6b764b648736b9f4a1a335463c4de7076a2be3bfb7bbcd04e3aaccd2
-dist/2025-06-24/rust-std-beta-arm-linux-androideabi.tar.gz=3ade9cb0c40515ed3b1601ec66bab1cc81f46e9814790a3589259750be8c9ec8
-dist/2025-06-24/rust-std-beta-arm-linux-androideabi.tar.xz=cf6997822547dc1b776443cee80acff76ec66747e6cdb16784d81877922a9d57
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=09525696ac31ab025a27cd61daa457f6687a526e4ecb8fecb87e0152fff65bcf
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=d5cb742fec22224144fde555dcda683a3efa262d1c7e7986e038fe545d8ad9e8
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=ae119ef640163fe7c73179d0f895794520c790b05decd31548631f288ba6d01e
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=11f07bc11660e4a4b6b2a97d26cfa31c36976fb74a36b5dba7dd66c4bb81608a
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=2c9f4567c766e85152981a594169f6f656d89048947d2d9a30ff805ca6f1e59b
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=427c70145dc35701b0888b7863657ef0fd5d4b7bff7081e984a5e977d423c7f5
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=c042af9e0d8fb02ed80b57bae19ed8608c005dd279ec1c64dde53d65752a0b14
-dist/2025-06-24/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=b6fd66abb9f14c4b8bb43d6c8b32d9aa666be01468b60768fc8d0db4414da920
-dist/2025-06-24/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=896294c85fe8570f024a08aa0c22668f38b998dabb0008e5a4f8d7e1ecb2236e
-dist/2025-06-24/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=03a2a8658186e48c7bffa4b120821e99d4066fd115b550af4d76998545e1fb24
-dist/2025-06-24/rust-std-beta-armebv7r-none-eabi.tar.gz=3302d8df9dd73c44603b7629ece46a0a0c1f03a838a354973fe8aa2ed13ac10e
-dist/2025-06-24/rust-std-beta-armebv7r-none-eabi.tar.xz=3c9d1278136a92c6c829a07eeb991f9047e703a82145af2ba0373c0d01429ab4
-dist/2025-06-24/rust-std-beta-armebv7r-none-eabihf.tar.gz=864a261c4c337e692d4c3aa0f2659e9d87ce946309d0e61fea752f4fd7835a6b
-dist/2025-06-24/rust-std-beta-armebv7r-none-eabihf.tar.xz=ef22b1321da09ac6d64b5e965c02ab0886dd9f4281520cad4050764203b153bc
-dist/2025-06-24/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=d057fd26541f096995e3d774659d5d8b602e67354b8551f0b99c7595945aa194
-dist/2025-06-24/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=afad054eee6bcdafbb68308d7c53438e561ec26196683552d2f825c63948d325
-dist/2025-06-24/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=65306dbc9e7d75810b28624a9dc146034b3c7764313ddac084309a36e688ba0b
-dist/2025-06-24/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=ed4f9cffcb7b1bb1bf72b952afa422cfbc74ab9e04d6acb750126da5d0f24094
-dist/2025-06-24/rust-std-beta-armv7-linux-androideabi.tar.gz=7e39283a3e4e469e6b9dd35497515481a9050fbc1fb9f10334cf495b3c34980a
-dist/2025-06-24/rust-std-beta-armv7-linux-androideabi.tar.xz=7af0e068e2ebad42c79926ff1480e4ec07d7a48db142a497fb8f75b7a065e0fe
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=677d3328d721fbcf515bbd0628b59dde2ac1e0d7ed567f2784666430d61e391a
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=550c6df5954535165b55c07411144a122f8156658c1f46f74a71a7f17974fd29
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=b5deee5b5ba9048dbfc1c416972df6a4d42d52f4a6d1857757e0d01d8c47a824
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=7f898d3e1f6ec6d53a269803d4d4a248e052892bc9f46c3bb9095ffcfb0e04a5
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=56f8943fc65b732dc971f01bed589d9fc19a2a263a4af4f20810f7b586ae391c
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=1802d041656132519baf110e5a072260a7fe809fda87c6e01fd5fc4809249f8e
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=36917662d6e98b19782c9d81087857f52b7dfdbb37872387285c9507a1bff391
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=e6aec6411c740e5470879e64c85882cf3627c24c7d584f359c77397a782a613c
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=0c9a18a6b7a7c981c5e0ef337e66915d14499c6392bbfeb55a65c4f3340a4835
-dist/2025-06-24/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=f1cce70c71bb712a9aba0827ebb7d5783b977a674606cf5fe10879db81627c5d
-dist/2025-06-24/rust-std-beta-armv7a-none-eabi.tar.gz=d477ce01b099b81e96a9edf6617c21725808c4c234c4ab2f84216565f6a6efcb
-dist/2025-06-24/rust-std-beta-armv7a-none-eabi.tar.xz=a2339cd5cd3dcbb5b897740b7e7bbf6c5130feb1f6ef7c2c09012eb6cc79d417
-dist/2025-06-24/rust-std-beta-armv7r-none-eabi.tar.gz=40fd9ed6b6b428cd476f690ebd3e2265cac040f4772b91af76b071115b16b9aa
-dist/2025-06-24/rust-std-beta-armv7r-none-eabi.tar.xz=c2dae5167d4f7f6e1d797b065404cb647d102d0f0165fff89d040c5c89faadb6
-dist/2025-06-24/rust-std-beta-armv7r-none-eabihf.tar.gz=c4731d34cb23614cda51fba5e66d6327c653c21df71795bdbcfa48f20aa0ef17
-dist/2025-06-24/rust-std-beta-armv7r-none-eabihf.tar.xz=561f5934f8bcbd9860f7b042d9baa4d4ffe0696eeb3a0447ae04467497b749ad
-dist/2025-06-24/rust-std-beta-i586-unknown-linux-gnu.tar.gz=035ad6be061e3a3bbe36baffd1bca5cfb91d827e07b441e3e2c32b0b9e1212f4
-dist/2025-06-24/rust-std-beta-i586-unknown-linux-gnu.tar.xz=5ca691898ea3cc66822aa32ac9d24996610cd79e34275b35a53e252f5c99fae7
-dist/2025-06-24/rust-std-beta-i586-unknown-linux-musl.tar.gz=614a68e5593b672f87601c07f95b30324a3a60e10ffe814fe2a772d533a9eabf
-dist/2025-06-24/rust-std-beta-i586-unknown-linux-musl.tar.xz=78f7ed2c2f0f3e0e0d883ffc94a4fae43e7e5f3fff6e91e16d8a459a40570fee
-dist/2025-06-24/rust-std-beta-i686-linux-android.tar.gz=d6e5a0fa260c5222e4cce351be2eeed9b85951a8e79bdfe379a4fc2be354d558
-dist/2025-06-24/rust-std-beta-i686-linux-android.tar.xz=3e0c1ff1e8528a7c0a6cda3a7a90c2ee88b0b1b697b2430d410dad944df11a46
-dist/2025-06-24/rust-std-beta-i686-pc-windows-gnu.tar.gz=f944a4982a6ca520284bcc5633f05226f636747b8df4325ca1a2c77049e2ebe7
-dist/2025-06-24/rust-std-beta-i686-pc-windows-gnu.tar.xz=6664ba19dd85737fb5276e8e83a30989c49e795dd4608e67f33f4115253c0753
-dist/2025-06-24/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=9e7e7838710db5f340448e957a5ba812a3fe91baa40ba68c355fdee653b0413b
-dist/2025-06-24/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=c5d4c6274444e695630309ca66fd52f08645eefe424b5e287e89064eb10aee2a
-dist/2025-06-24/rust-std-beta-i686-pc-windows-msvc.tar.gz=e1bdc0d04736e0bc95e131eed25944f62a4d2896d80778b8a2260df38e0f9946
-dist/2025-06-24/rust-std-beta-i686-pc-windows-msvc.tar.xz=7df4a0e74e6ad457fbe38d0eaf40a3d190f0d77d6b4d1d3940028e9c7935558b
-dist/2025-06-24/rust-std-beta-i686-unknown-freebsd.tar.gz=a791a76c83a257590c8ab653b92ce65d74f4885faebf64c91c111363d237aeb5
-dist/2025-06-24/rust-std-beta-i686-unknown-freebsd.tar.xz=7455eb781d0e1a0b6a154e93d7cf2ae2891f20fd77b8a2a0a3011e94a5013147
-dist/2025-06-24/rust-std-beta-i686-unknown-linux-gnu.tar.gz=c6f770e2cf229e97640845137df23a7da8f6e6e9753d494dc9d5aa8dfb506e95
-dist/2025-06-24/rust-std-beta-i686-unknown-linux-gnu.tar.xz=d7c351e3a45181f040acd5f8c20c655d878a0d53927489891603b91c80c4abb6
-dist/2025-06-24/rust-std-beta-i686-unknown-linux-musl.tar.gz=547a90d1f7742389642590bfc45b66474febebe3c6c5209cb1b22773e65ad03e
-dist/2025-06-24/rust-std-beta-i686-unknown-linux-musl.tar.xz=6c7476b7b93ac2a97ec5385ecb55463b11118b84aaf9a155a1cdbb68ea879241
-dist/2025-06-24/rust-std-beta-i686-unknown-uefi.tar.gz=1f45c12ccc6d27bc6931a6348dd0a0a3f4e5eb63ad45e4ec362f706bb327ee24
-dist/2025-06-24/rust-std-beta-i686-unknown-uefi.tar.xz=43c76c933f3eee6f7c4230fd34e702a59b5a5ad088c9bc20112e4e0b2d5dbaae
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=caed38451c419ab05e54b8d20f6af56a274b3c59b000a0ffa51b7b63ea314c27
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=5418975da12a39cecfb1a040dbb2ae6b8b63a76b652aca582ce04aeebb3c05fb
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=b0d0856119c2b15f1ce6c3fe26e9f50550817c896235784333afd502ee804957
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=22c39fa9a460b12e782951794fe92537fbf8108db1e4cee4c641a07d9741145b
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-none.tar.gz=2433c862a1fec8a983112f6472bdd0e6bf9ce66ce9484f89b78d80c65375a70e
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-none.tar.xz=dfff451f7f16c309cd0335def206429b2f10ab4943d59dd7cabe8afd8c072dfd
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=d975fafa4271c774d8295cd93944ca91528960c12aa087435074b78c0ad783a7
-dist/2025-06-24/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=561172fcbb2448dfa60a0daff761d8e6022543dbff191b584614adfcef8f255d
-dist/2025-06-24/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f381683e2aca2a54f9aaa920c71eb8a06f50edb2967968b63a32a53bae3c2e7f
-dist/2025-06-24/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=e09536466bf24c3ddf250bcd4e92677446341902e6c20bbed7f20a9a11250462
-dist/2025-06-24/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=56484912fc1ee60288b5739b5e08680361cf8abbc927cb30012f491e77483192
-dist/2025-06-24/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=96bb329f992b3c8e060796e52aca2ba384225f350ccc2c12d0aa8022b1305842
-dist/2025-06-24/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=806c017f5a94c70722ebb38d4e2ee8fa87d5d53b63712763114fc318d33edb8f
-dist/2025-06-24/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=e4bcfd4ffb2db92ff57f881875755b9808744c8e59efb2a3ae9c215a05e696ea
-dist/2025-06-24/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=8082559bc3da5b9e6e39732e83682a892df8535f75321710c6e5748f6e7e1985
-dist/2025-06-24/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d05626a5f3c364aba66aa214530fbf37a38b7c613c8c1a54c5ba46d66477db96
-dist/2025-06-24/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=03690be0e07e3158da23750b4fc063c25b5760bca3447877cbcd45707eda9780
-dist/2025-06-24/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=4b1997788c727c36a64eb335de3c7d8f100c3825129a1e4a2187e3a23851f083
-dist/2025-06-24/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=421dd99dcdc80a55c8a159d22c3c596424029f1fa1d7c12bfdc7b718091b776c
-dist/2025-06-24/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=1a574ae822a4ad793c10313d79dd5566d9ff74d7a7b83d860e06df0aa752a151
-dist/2025-06-24/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=0b0891369b16ea1480554b2670311aaf6b7937420056d04b1ce2c80ef3955bb2
-dist/2025-06-24/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=366db574f295053b2bbdeb35a7c597fb624396b1896bf482067d5d5cee7e4f19
-dist/2025-06-24/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=813cced4f75479412b22dba98148036da9ccfe9e1181009b8ca99f3e12398932
-dist/2025-06-24/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=5378810bc555e2d4be7bf5d43731649f803943854ea23da7a36887254f473a59
-dist/2025-06-24/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=709c652ec071033227867dd87ba19483e30f6f68e95b36c448d46b0321b693ef
-dist/2025-06-24/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=cd6935d932ef81beab950126dd932ee6d0fa11105974f94485640fff894c1bc8
-dist/2025-06-24/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=43ac51227f85776f98c91dea378b765cfe870141d6bac7ae8aa0cbb0ce821de8
-dist/2025-06-24/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=c5ddf06de14b22ba431c1f8d1944425ea325b0cc83c3f2a2ee85291570187824
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d45fe2a30afd25bb2975e006cd17b612221a710814611670d804a9bd2f4efd84
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=b43a87dbd6ab3b3d440f2bbeeacc77719d29347b980e74160301539902f039ea
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=cfb5d97f24c7daf95d833b519a8912b2fcdaba31d8d1bece90c406ae8a2ebd32
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=66e5fb37d89bd0fa7b8a2721f4b610711ca6069f9e406c5cb9b90d792e70b5ae
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=5e1f10a92f1ca7bd4a0325662d15933371e756f0eee554e04b525f35b036e050
-dist/2025-06-24/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=7c09140b3af9ea56fafb724f66bb67d73bc788d139330b373eccd9fecf014024
-dist/2025-06-24/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=1c41567f55b86e683efff62f0fd397dc43324e2e664c0702f1c79db8b407759b
-dist/2025-06-24/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=63573b32f25f53bfe42b1a4beecc75dba0f0e8f02be9e680a45a2429a46a6f9b
-dist/2025-06-24/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=3725c30ee0938a4cf3c9f29e115c61d8045f437c06887e39644a1211ba18a4b6
-dist/2025-06-24/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=2bb94be7f6ee32bc23748e69e399a5fd087671e3e4fd8d77e819e51dff8cee5c
-dist/2025-06-24/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=b789df52548c45c070057ade63f1d6351ba3cb39403a9e33c0776bafa5985abb
-dist/2025-06-24/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=84179facb34fb286545622407ac6bfd5bb2b7546e02e56597152ab5bab49fe93
-dist/2025-06-24/rust-std-beta-sparcv9-sun-solaris.tar.gz=ec9de10d91c1f912d97f2a96aea58e6c7cca5ab864a14a7aae62064c8ddb1e53
-dist/2025-06-24/rust-std-beta-sparcv9-sun-solaris.tar.xz=6628f2b64f56ff05ac18bc7486231a3f072de23979de2bc1fb7133670e32f98e
-dist/2025-06-24/rust-std-beta-thumbv6m-none-eabi.tar.gz=a202ee09869f4902d1769b42cd05a992293003f92d4d62db8d87c195f9c9dd9b
-dist/2025-06-24/rust-std-beta-thumbv6m-none-eabi.tar.xz=e34431bd5a7a00fbc9af4ee5c697b7244cf768477e05e68c6739a4c9561feb11
-dist/2025-06-24/rust-std-beta-thumbv7em-none-eabi.tar.gz=681da6a51ba84e4f517f1390ff4e8c09fbb9cca0515e67ce074c3431d582cc7a
-dist/2025-06-24/rust-std-beta-thumbv7em-none-eabi.tar.xz=ca7a21b1e58625bed5a9d8ee9e20ae7fd33fc822741e1aa8b4cf2599e45f6edd
-dist/2025-06-24/rust-std-beta-thumbv7em-none-eabihf.tar.gz=51f4d95e11a9b5dc59534e63277c1567e8ba8edf205f50bfb857d0bc2d2a0a16
-dist/2025-06-24/rust-std-beta-thumbv7em-none-eabihf.tar.xz=066189a75cba466b8f6881e559c5501a987741a5314a3be18045339111eaff67
-dist/2025-06-24/rust-std-beta-thumbv7m-none-eabi.tar.gz=97395d2c7f9ffca227434df59925082be1c19656f78af8914886e37ec687bac6
-dist/2025-06-24/rust-std-beta-thumbv7m-none-eabi.tar.xz=9904335b8a696233694a96538d965a8ca6b62a1cb8e155818061fd1ae3f7d8e2
-dist/2025-06-24/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=8227426bae9b1c242deca19312af3bb3e64fcf736e7902cb74daed2e3595bfe5
-dist/2025-06-24/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=0908f15689366fa9cb3a6acf5f85a6355aba2f30387d17b0ea51edef5a7903b1
-dist/2025-06-24/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=f2b3fec136958adf29a43d3307505f6fe79fd0e00f9abc42a56c0a04fadcf227
-dist/2025-06-24/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=4520b3d88a48e054ea4c243904d3c7fdaa8dda0a448e48014d78d9ada1982220
-dist/2025-06-24/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=da25e5bb90b522db9ab502068b7a7f4ec0a9ce7fbc0b98949e345490ff5854fd
-dist/2025-06-24/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=eebf1b73a75a4dab88bcc70121c024f40184ac30668ff298620853bd770a6e03
-dist/2025-06-24/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=ad77f75d12be96cd135cb7dec17688635f98101072c014724e118d1e1d124afe
-dist/2025-06-24/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=038927ed53bca15d35ceaa33d9d8ca3e21be380d853b67404535317327e42ec5
-dist/2025-06-24/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=e5f4e09db94d0a92985bb4e0e72c1cf9402c81647bf4ee2f56b5b0626da1bfe5
-dist/2025-06-24/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=662c722d3445141d1f3aeb070e789c5115776a3dd909faf5a39b9ce3df8c8933
-dist/2025-06-24/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cb2630b14ef721b43366e8f6135fb37ec3d2185951bd66344e329644fdc31812
-dist/2025-06-24/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4c7e117fa93c9220b5e6103fb7802c18b4a6c53f2836480d60263046e73c3a8b
-dist/2025-06-24/rust-std-beta-wasm32-unknown-unknown.tar.gz=1e9ac4f3fb341dfb1719fe5643e7cf867ebe69172e352ba94fb18b63bc2518e9
-dist/2025-06-24/rust-std-beta-wasm32-unknown-unknown.tar.xz=c207fb92fa666f3113c451cd584ebe666e36d6a1b97a3b91be1d513920ddf26c
-dist/2025-06-24/rust-std-beta-wasm32-wasip1.tar.gz=e68f2697d3824721abeeb1d953455dd3d54ba8549d3b7c6998f00869747f3e99
-dist/2025-06-24/rust-std-beta-wasm32-wasip1.tar.xz=46150b8817705718589a85bf9b657acf60bd9c8829cb42fc4b59264cb357921a
-dist/2025-06-24/rust-std-beta-wasm32-wasip1-threads.tar.gz=1a718af362f1314cdf934901b4eb26c8ea678a28009e8e725d46452420b1d7c9
-dist/2025-06-24/rust-std-beta-wasm32-wasip1-threads.tar.xz=f4c785ae809fa803562e2a1e406fd7a0362f44174e40913803e3332672bd1e40
-dist/2025-06-24/rust-std-beta-wasm32-wasip2.tar.gz=f17386b04a3f003bb42ca83a2044b23bb1b766b65b64b44c10e9d24f09a1bfc8
-dist/2025-06-24/rust-std-beta-wasm32-wasip2.tar.xz=9f90613dc5c6f659087144d6e25b091cd1a6fa09697a0d2d4c896bf74f473d9b
-dist/2025-06-24/rust-std-beta-wasm32v1-none.tar.gz=753c77345c3b1fd7407a69d29a3cf3fb8c2dcd813c2ad63c1e97fe0dcf203f94
-dist/2025-06-24/rust-std-beta-wasm32v1-none.tar.xz=3bee75d197b4679c2355fad5739aebf721b182e93bfe76f1b8b9e004bd146d5c
-dist/2025-06-24/rust-std-beta-x86_64-apple-darwin.tar.gz=aa7ac11017e96b2bc2c103c160dd03aa0e1826034c30a417b11d67b9fb657f2d
-dist/2025-06-24/rust-std-beta-x86_64-apple-darwin.tar.xz=89a065f72d284cf2f886b7af2edc89f89812531d85aec8608ca0c1516365082e
-dist/2025-06-24/rust-std-beta-x86_64-apple-ios.tar.gz=b814b2fb46db55b18e1b5bcd0ceba73745ca6f7a57afc7b90009275d61bb95c8
-dist/2025-06-24/rust-std-beta-x86_64-apple-ios.tar.xz=5a82ad2a7e45df8f5f1c374ac5bef2dd4f7da81dec2a348c75593e1bb752dd40
-dist/2025-06-24/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=2482863c941aec4d9de753a8787961206e1ba8129180e2e85a4ac3eb158ae8a7
-dist/2025-06-24/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=744d487c980f455d967df95c466399b181a891a879c25eac677fadfd87ebbaf3
-dist/2025-06-24/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=9ebd84ebf36aaf8707268965ccc9efa69b259edd7d3a5fe13be4d21dc63f6bfd
-dist/2025-06-24/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=06020c24f4d5b339c794cd16fe87b1fd7f77d8d54f9d83f0d6088fbd062c900b
-dist/2025-06-24/rust-std-beta-x86_64-linux-android.tar.gz=f5054210cba3367f5c9fc0c37b7f2cdfcf90ec624e7b1b3cddf24b2bbba53c7b
-dist/2025-06-24/rust-std-beta-x86_64-linux-android.tar.xz=65dca5fdb5c9138b4361819aed754a574d74bed1a2d7a7aace1fda15821ba2f2
-dist/2025-06-24/rust-std-beta-x86_64-pc-solaris.tar.gz=575392afe724160d65c05dcfeda4d9b4868c182aefd8981a4b233222bc1168c1
-dist/2025-06-24/rust-std-beta-x86_64-pc-solaris.tar.xz=f385ad71529ff286607a461c84a15df81e9a8f880ee64a50cff8979c52262f27
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=647b7e4a44d1802721461e6c9d6ab1f7e148183476c01e410b7052e485081a61
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=817535fcf0efdd1e84ed85787fce6e674c22b120bce0c8aa1dbe53b2b41aebdc
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=c6486c9cbf372d64858d4d251750c3dcf07e95d58b55ccec87a4c71292eb7d11
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=75c3f76b85534f0d058913328b9ee58c32a3a08414b4c5e7a046a87970b9eba1
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=d61125fae17e7627e7b56ca4ed32500b48a146d000e4a723ba34780568d8c0d0
-dist/2025-06-24/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=590b14dfe52e3a286763d19ac19a83315c47f33a284d59169e145c8860eddfd3
-dist/2025-06-24/rust-std-beta-x86_64-unknown-freebsd.tar.gz=76e7066a540a06ac241a11df8fbefd511b48d85aa46f380a8b122bc342395faf
-dist/2025-06-24/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7cc4adb3c102eac53916b28c0dad40bd095e19ea3fd0430e84a2e0b094445809
-dist/2025-06-24/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b6b97c0e0348051a314bc705d8361f5609c63a42eaa3f85081d004c0258ac9fd
-dist/2025-06-24/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=5dd625fd17faa417e1c0abc5aef7a3f40d16122227c8078f8e0ad2530ef6d271
-dist/2025-06-24/rust-std-beta-x86_64-unknown-illumos.tar.gz=92bbecc4de50711693b54a11559a07f17569f60b1600ea40d6f6ce2e3a24ad10
-dist/2025-06-24/rust-std-beta-x86_64-unknown-illumos.tar.xz=fe3cb8e3adb7f4fd5f64feaa57587b4e41ba7437553e94a36f59a5bdca293f06
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=a81e77c04cbc0b0f456c117361e695b78ae234cd53043368e62dbf10810c2c8d
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=c71ecb0a0c44cb7a9f35b6fe71e73f605d025af16f1ee5f1fd9c8a432144c54a
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=2fcfa0c62f69b5e6d78c31596e7b6136bac38d65efabdd8fafdedd731bb124cc
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=b2cced1e9ac03a4aa4f39de7ca6b8ed8cef2201bc851a413214e414001601ee9
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=178fe4f5b68e65450abaecf5c45c29e2a458bdde9b7c16f59755bdb1b4c1c218
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=eac7c2aaf40a31c2fb9fd792bacdff8b573f2fdcd2e52f4c7e798b51e2586652
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=0c481e67a034eede634c201c88aae0cd2ecb36c656256728aff44b211657ab45
-dist/2025-06-24/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=4a1fc452d88bce5100d0da49c0a42621296731f7584de1e7869ec41800454bf9
-dist/2025-06-24/rust-std-beta-x86_64-unknown-netbsd.tar.gz=f7cb4b3d73ba6e571b77e5b58d877da5f89664d0107360f7c183c45df7b98e2a
-dist/2025-06-24/rust-std-beta-x86_64-unknown-netbsd.tar.xz=6dc733be1457802f8c54a6f2bbc6f337204c2baef693888c1302b6f2df11e7aa
-dist/2025-06-24/rust-std-beta-x86_64-unknown-none.tar.gz=16e3765f0c5b017ce3f6e2f3325c30e27eabb85fae1d935198f376fbe33e2551
-dist/2025-06-24/rust-std-beta-x86_64-unknown-none.tar.xz=60c87182e6f9d6ce4e8e612ac6aadd3989e69073f5fa0774d0e8dd76a47d122f
-dist/2025-06-24/rust-std-beta-x86_64-unknown-redox.tar.gz=757169fa5abdcbf592aecc8b77a7ac48de7fad19a0cc714e5e0c37f0c887b36d
-dist/2025-06-24/rust-std-beta-x86_64-unknown-redox.tar.xz=9888201cd4d10eeeb5b4c342aafcc10b1933f32df7e90ff2e9cf6ef0be6759f7
-dist/2025-06-24/rust-std-beta-x86_64-unknown-uefi.tar.gz=9d84268a50c1a730eb999761e248e166942dffbed9d6ab92ee1ef05ffa43d133
-dist/2025-06-24/rust-std-beta-x86_64-unknown-uefi.tar.xz=3ac1e6eecfc611b6be02a10eb4708c8d6932dea2004ed8c8441a619a61eb25f7
-dist/2025-06-24/cargo-beta-aarch64-apple-darwin.tar.gz=6dcf7741941f12ffac96f8210c9cafc3ee68bbed9211a95bcd33e1e835454b31
-dist/2025-06-24/cargo-beta-aarch64-apple-darwin.tar.xz=39d6bff308caf2fd5550325f2f930cbc3d77dd4f385d21e0509688d2203acdf7
-dist/2025-06-24/cargo-beta-aarch64-pc-windows-msvc.tar.gz=ff9d9c47fc85ee51ac1194138b25d8626704621e38871bf03a7e1c015c88ed60
-dist/2025-06-24/cargo-beta-aarch64-pc-windows-msvc.tar.xz=459006cc1a313e9ed28665015dcec313413722df20de729dada4f9e5a11d4809
-dist/2025-06-24/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=62371da9200aa838f8e217347c3aa5568010d9fc2d963077e785d0f7f75417b9
-dist/2025-06-24/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=cf7ec78f834f41c658179524a741b472c7ab4bbed3d6c0d7f61e7147d7353a78
-dist/2025-06-24/cargo-beta-aarch64-unknown-linux-musl.tar.gz=2ba26fb886020b136b6635ad89caa96d995c4179ffeb4c06bd8a5484c6e94669
-dist/2025-06-24/cargo-beta-aarch64-unknown-linux-musl.tar.xz=343f471ea1df375de51b881b6829855ca060d8e9e6bf3b066123d3e7fc348c18
-dist/2025-06-24/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=4f03751e62a43cfe8aa9528a9af2903bee629ce1d7eb808a3f5c9881e7c3fa4a
-dist/2025-06-24/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4082553dfb3af462d9e70c1c13b505dece9a0dcdf5584da2a311d7d6c4e45838
-dist/2025-06-24/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=d80111e0b74f8e9d5412307c6dffe53cb77a8febd25ae6d8e66813aefa56a7e5
-dist/2025-06-24/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=d06aa271a329ba63c4d1a3a6adf6ced0c5c1b900b20870c666ba6764f2d5e5cd
-dist/2025-06-24/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=5509454a5390a5732b340959974dab97e31b6f307d036e55b788633cb21e6f54
-dist/2025-06-24/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=bc6e883addc936fe55009fa854922c2ec405ee2c085749476bf3848070098116
-dist/2025-06-24/cargo-beta-i686-pc-windows-gnu.tar.gz=2afa312411c50a629c62661d245f3672e305d7f083494cb0dc8034a726c72a54
-dist/2025-06-24/cargo-beta-i686-pc-windows-gnu.tar.xz=67e0cbfff31418c767e81bc45ddcfe6e9a47b0f279b49c0b0cad84aa589802c7
-dist/2025-06-24/cargo-beta-i686-pc-windows-msvc.tar.gz=1a9d5cf8c1dbe182b224687bdba0026120fc684232a89488db52160dd6f8145c
-dist/2025-06-24/cargo-beta-i686-pc-windows-msvc.tar.xz=9ce77b6d3ffbdde316b54c1abc6fec888ea5d4307e0a4bab7555b9460122e3cb
-dist/2025-06-24/cargo-beta-i686-unknown-linux-gnu.tar.gz=1d9fb35b564e718616ae2766cbc99e041d4e9d53bb0d8f885cf971e0803c85a8
-dist/2025-06-24/cargo-beta-i686-unknown-linux-gnu.tar.xz=c0c5c0f72726b577fec05670b6f9d46501b79af55c642d2b2f58a88e731db7ea
-dist/2025-06-24/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=2bd4605054472e27df314d795c524126a2ab54e9f37442f579e6d75b8a7a0534
-dist/2025-06-24/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=7f8dc8897f88659268ed0247bce6fd35b4de813fcac5bd488d20c28504bee028
-dist/2025-06-24/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=dc52a8982e04f52b5c42a09c3fabf3529b3871d90039299ddbc2648713e3b8f9
-dist/2025-06-24/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=c25a1beb08ba399a98eb77c4baf4bcad80003eaae09fcb7cb6253943d5ccbc05
-dist/2025-06-24/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=4d0841925d6f2664b4b110b4fb3f3c62a64b34b925722d08cdcb2b568e3f0682
-dist/2025-06-24/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=c81c32af1c4e7e432112515af1dbdd6e4adbea668710881b63af7acd5c4715f9
-dist/2025-06-24/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=08d06b8b77148626bb2bd17059619083cd13d3d3f344c146dd509bf5d0d3d7b1
-dist/2025-06-24/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=55cd74747e6993eee6ec3aba36a79d108bf952d64a646696883e33798b27ade7
-dist/2025-06-24/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=eea9d0980545cd6ffde6ea512255cc2d66d335c23a8850695c87885bb931183c
-dist/2025-06-24/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=7fe952473dca82b599745a9f3578b4976e43a6f91bba02a59da216a748d3a3f7
-dist/2025-06-24/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=6cba20c43713901144fe4542c4e410299e12306448d214614c19dfa201ee7853
-dist/2025-06-24/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=2c40f5715befa7938c3f1c2a65a787c497e97eb57bf03a82fba96f3eb55567a9
-dist/2025-06-24/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ad81074f9ea5c4373285dfaceafcb0d00f3372ac1d0655ac0ad0b2af816809bc
-dist/2025-06-24/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f963720adb03fdc4508d7037937345109973e1b15f9590ba7393dac26c493b6b
-dist/2025-06-24/cargo-beta-s390x-unknown-linux-gnu.tar.gz=b053764c635f2a943074c6f4b9f615ce6324d4c488143086ce2ead7d5e685790
-dist/2025-06-24/cargo-beta-s390x-unknown-linux-gnu.tar.xz=a214a89077adacb0e73acf6c7b0a312822eb72313be88aa5a1865dee7fba8dbe
-dist/2025-06-24/cargo-beta-sparcv9-sun-solaris.tar.gz=c2d95ad154fc06aefa53c54e5a71f019b46146d2efddcb2f605977a393dacfb8
-dist/2025-06-24/cargo-beta-sparcv9-sun-solaris.tar.xz=a4c001aa2a9def4fce93d910e0afc3dab6a8fa2c767e51f5bf5ad05b9fd8c2c9
-dist/2025-06-24/cargo-beta-x86_64-apple-darwin.tar.gz=3942f0f82e2797f146f171e69a4ea0c58c6c37aca319bf9a80ab3e96bb540407
-dist/2025-06-24/cargo-beta-x86_64-apple-darwin.tar.xz=07c111b584a728a6e1ffd2694864eceebf3cb6c58c6d860778f8266ee050fe50
-dist/2025-06-24/cargo-beta-x86_64-pc-solaris.tar.gz=175f782e1e9d4aa0fc12b618f46c75077d63014ce92e07b6a9faecad797ef787
-dist/2025-06-24/cargo-beta-x86_64-pc-solaris.tar.xz=b8c317d244fafbfbaa702b3fae80db1119f9e5804c30370c45e5070915241d29
-dist/2025-06-24/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ec0a52c99193bc8b995627809ca18f09e3fd7ea2a7a2eb9cf02a7af0012438c4
-dist/2025-06-24/cargo-beta-x86_64-pc-windows-gnu.tar.xz=a85b1e69b0ecb3323f1ba57c99c6ab62befe0146ca52905cc7db063dafa75667
-dist/2025-06-24/cargo-beta-x86_64-pc-windows-msvc.tar.gz=c775f0978a7a7f09b7277e41ff4c07f5cf7d2bd16a15dbd6cc89217c79192a56
-dist/2025-06-24/cargo-beta-x86_64-pc-windows-msvc.tar.xz=e956dc392e72fae8e42de5450c53c30e2fba56656cda1c6d5307ddd0d58653e7
-dist/2025-06-24/cargo-beta-x86_64-unknown-freebsd.tar.gz=2c8abc632a6e197fd93ccac1f2649247d31ad48519c5ad12a2b9c059e6725bd1
-dist/2025-06-24/cargo-beta-x86_64-unknown-freebsd.tar.xz=be762a368c6dfbe47a0f8c4b09cea1755a6d311f713b57b57a87276c88e5c34d
-dist/2025-06-24/cargo-beta-x86_64-unknown-illumos.tar.gz=6a2f8043e69c1297da8084f3c37695dfccfe30c4b23f7607e39e55ba3bfd082c
-dist/2025-06-24/cargo-beta-x86_64-unknown-illumos.tar.xz=471e9de6a783b7be80e44ad7626869ab06f03df9de00fdd35e9937607c259314
-dist/2025-06-24/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=634d3c89c05ca3b9f4579dd607a2122b03a15b342e616bb62355d642c286dcac
-dist/2025-06-24/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=93eeaf15597a264f552c6d60d3d833f15503f6dcc7d909f4138e1daedd56bdd9
-dist/2025-06-24/cargo-beta-x86_64-unknown-linux-musl.tar.gz=e8711c3926302bf6e2647d19028716cbb6c77c2e858c6d452f61d2d0a65df559
-dist/2025-06-24/cargo-beta-x86_64-unknown-linux-musl.tar.xz=a34fc3ab20fecf5221014068128c9ca5806788d16b7c0e2b490ad2e611614388
-dist/2025-06-24/cargo-beta-x86_64-unknown-netbsd.tar.gz=7afdb8922a69f922fcfee48e8028e0541b66fd34c18dd64f38b76477efc4744b
-dist/2025-06-24/cargo-beta-x86_64-unknown-netbsd.tar.xz=494e3e4648b22e285a763c190dc510ce5b75495da4184bf3feee3b77107a4df0
-dist/2025-06-24/clippy-beta-aarch64-apple-darwin.tar.gz=a8d3580790758c6bff3972a189c7e5f18472459c533368fcd9d04c40338166dd
-dist/2025-06-24/clippy-beta-aarch64-apple-darwin.tar.xz=9af8d1dc8f8111e26aa509ada13561b19dbf3f47e3416faecc170abdb433cdc2
-dist/2025-06-24/clippy-beta-aarch64-pc-windows-msvc.tar.gz=866653887ddbb770d0acd843ab54bd688abd2f3a384bfafeaf47d0643d7c7be5
-dist/2025-06-24/clippy-beta-aarch64-pc-windows-msvc.tar.xz=62d0400196a347622b7cab566fe64a87082e94933d0d0f28c3f9d0b9682764b4
-dist/2025-06-24/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=2659dd96831dfeabbe2f4806ec67a449dca2d3f950f705280a99da9d9e1fbb1b
-dist/2025-06-24/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=3325ddf5704811e48b1f50daea60961d18296ac1626e68828c9eb757e52cf65a
-dist/2025-06-24/clippy-beta-aarch64-unknown-linux-musl.tar.gz=471b5577f82ceb6a1a5c7e017526835643472a30d51ac023c7a758ec77166691
-dist/2025-06-24/clippy-beta-aarch64-unknown-linux-musl.tar.xz=9d5a3296f07ba65b576ca4d3de09d26b476b390b876dc8c8e4eac2fff1270cc8
-dist/2025-06-24/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=d2e1316aec639089a7d18ce41a9eb9c21317e25ba06c20f0551675a8aeebea43
-dist/2025-06-24/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=027deae3f2518ef33f41055a8a11ebc32697bb3499cad98ae89a05d9c5bb354b
-dist/2025-06-24/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=d041ee879d9489d4258541041478b3efd9c6a89dee97892378269cf2cd2896b5
-dist/2025-06-24/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=1f5a4a3cce223b750f271f1ab469939d00055795a752a0c88b1b49f00f2f42c0
-dist/2025-06-24/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=acd1d67dfd4176d2fdec865b4027492f43be7aa1d0635e6777cc6862dd6e306c
-dist/2025-06-24/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=e79ba7baa995f160561868fe221267b1b2f448a932b518fafb3afaaaa1028b44
-dist/2025-06-24/clippy-beta-i686-pc-windows-gnu.tar.gz=ee9c369d91d58aac3894a40500e0c8b0c4136a82cc39b2e44c9524a8c6e0d7ca
-dist/2025-06-24/clippy-beta-i686-pc-windows-gnu.tar.xz=ddee9ab89250fbfa7f45a5121cdad5cb1a2fcc010e4a5082392862f7c0033d45
-dist/2025-06-24/clippy-beta-i686-pc-windows-msvc.tar.gz=8ea4c8e4bb9ad9447cbf7c648f36378911d85985fcb5af13908a89180443cae0
-dist/2025-06-24/clippy-beta-i686-pc-windows-msvc.tar.xz=bd57be99cfa8eedd284d2bc93a5abf74368aae021e83a367e426e4be0193cbd2
-dist/2025-06-24/clippy-beta-i686-unknown-linux-gnu.tar.gz=973c76613f1d049708587b84006c408fd8c8d5cf308c572257e45b8e5e33bb4b
-dist/2025-06-24/clippy-beta-i686-unknown-linux-gnu.tar.xz=b84d9b6918e18540e3073d66e9bc02845257fe2f1a39c9e62b44e81f2aae341d
-dist/2025-06-24/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=dc4e842ce58fd07eb59cfdd870fa311f925e5efda1044bb51719bd250ff03cda
-dist/2025-06-24/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=332e8549d7bedf4f97dd9b1cb8a5af47fc56374438e8878ebad2593bd36a48b6
-dist/2025-06-24/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=d8181ee683bdd6831af1d882247353d2731ee08ffc0443a9cce0f6da44fc6b0d
-dist/2025-06-24/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=c7b0a21c55e36372cb1dabdacb58b45bd02827e08e6524dad97b74e6ed9de1c5
-dist/2025-06-24/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=38f2a198a952bb7002fbea1ae9a12ffdfb54ec774e04848b7950bd13f17199de
-dist/2025-06-24/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=b4f5e016c5035cd2b70d4e3fbdf1d0ebcd0d1cc6f1d297bc04f99581a02febc5
-dist/2025-06-24/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=1beac7db7663f460e548f0efe9ef1737d114c6b8aa56ec81e536e170c21231a7
-dist/2025-06-24/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=0dbcfc800635438f803888caaf37677b424ef5a90cab81ceaac627bba7faf6b5
-dist/2025-06-24/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=8c0dd34227e9b7a44ae8ed96be4110e10c01eafd46a7d050ab0121ca80f4fe09
-dist/2025-06-24/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=7a56be9e5d58dbd2531d8c049fada5bdff5d98436afb63b92ddfc5f58d5835f9
-dist/2025-06-24/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=6bf5ed0793c38fed42974f8d0ae9442b926ac1072b3af08f97effbf32c5dfa54
-dist/2025-06-24/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=79adc7bbc8e4623c333ad3600305fce3c34fd35dcb026a654648707eef87cc6b
-dist/2025-06-24/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=1f881bf6585354c5abadf2e7f8ba50247b47de0c317ab61cfcc550cb6755de6a
-dist/2025-06-24/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=dcfa6d2fcfb96aed0ce6df6bf53cb8cdfe8529fb361cfaa78b92fc8773cc7446
-dist/2025-06-24/clippy-beta-s390x-unknown-linux-gnu.tar.gz=307884da83f8b77d2bde49a522d586e22c95febaca197d95380c7d60393ca948
-dist/2025-06-24/clippy-beta-s390x-unknown-linux-gnu.tar.xz=46db14272bd41ec2b89d146f8d200cf21b12bdb1183fbc303f8e8cebdf11080e
-dist/2025-06-24/clippy-beta-sparcv9-sun-solaris.tar.gz=09fcd95262f04a5e858baf04f47dc02632cd6860a9e747daf78fe1aaf787153c
-dist/2025-06-24/clippy-beta-sparcv9-sun-solaris.tar.xz=28905a71542485498261529d8cc4a2a47ebca4a9bbc8a2ffb22dc3ebb5ac96c6
-dist/2025-06-24/clippy-beta-x86_64-apple-darwin.tar.gz=884844e318557cfe8a2175795ffad57919eb88c3d5246893e47fdb0db6ff9046
-dist/2025-06-24/clippy-beta-x86_64-apple-darwin.tar.xz=4b8594e3f2945857c4316fa7a46eb8d8ad025ae9b87af58fbb7b6913f843b48a
-dist/2025-06-24/clippy-beta-x86_64-pc-solaris.tar.gz=04a12879eb1fea5b646dfedda6f25bb349b1096d753137e41543f20bece4b6f8
-dist/2025-06-24/clippy-beta-x86_64-pc-solaris.tar.xz=4f3323454f0c53868637d98dae2d237b1d16857b18e8db40884e7c550ee1ca3e
-dist/2025-06-24/clippy-beta-x86_64-pc-windows-gnu.tar.gz=81eca7c5978dff34526a1e3921e42785190efe0e5064e006c677b82b6cab783d
-dist/2025-06-24/clippy-beta-x86_64-pc-windows-gnu.tar.xz=3f3fae70db224b98aa6d9ce38f35c31bccfecceb1c6111bf928008a545e93b48
-dist/2025-06-24/clippy-beta-x86_64-pc-windows-msvc.tar.gz=48ece2ad4610148df4dbf6c78c81c56eb66d3d3e9a8c08b8bec76b0abf640983
-dist/2025-06-24/clippy-beta-x86_64-pc-windows-msvc.tar.xz=b37de86534a8655cb41fac60c920d49ab3880b1ac4aeec124711fdeffb025052
-dist/2025-06-24/clippy-beta-x86_64-unknown-freebsd.tar.gz=140c8f99e13ec96256bbd50af6e8e3786885d718cdedadc2b2dc1d82cb3e5ab9
-dist/2025-06-24/clippy-beta-x86_64-unknown-freebsd.tar.xz=6f306a3fd1a920931393081ee431c7ab37f589bf7a449d36892e6b5945a71d80
-dist/2025-06-24/clippy-beta-x86_64-unknown-illumos.tar.gz=9faab86392b6d1ab0579f5ce61d94e2998357d2c8d82cb441d7a718ce52dd1a4
-dist/2025-06-24/clippy-beta-x86_64-unknown-illumos.tar.xz=ea03c88713cbe937d963a4f18e0cd5015aa2e5151e66cb3cb24eec76b56c4023
-dist/2025-06-24/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=13fd137434d475440beae2ad047b58853e54d1063396ecaadae316fe81d761ab
-dist/2025-06-24/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=c3b96035b40c01c23256ad5b4c2ba876e84e8bc5cfdc6c14cfc9d4eaf57fd74b
-dist/2025-06-24/clippy-beta-x86_64-unknown-linux-musl.tar.gz=2af28e2a0c1b8c6c41842b420251375dd2cd24a51cc0cfaf2de4bf3d49612a76
-dist/2025-06-24/clippy-beta-x86_64-unknown-linux-musl.tar.xz=e18561036958432a47c94c1b32202a3f843bf01b7a1edd61e51b835bee83d611
-dist/2025-06-24/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ea015d2b9148d77ef7e060bee4b190cc73e7b117420f60abc77aac2a2aec7e
-dist/2025-06-24/clippy-beta-x86_64-unknown-netbsd.tar.xz=0282575f3ea1476994940e0a97a5720bf4452be01e0360cab58eec12c0480699
-dist/2025-06-24/rustfmt-nightly-aarch64-apple-darwin.tar.gz=3432f8489fe400b73d3cb01e4e49fc3305a0e5207e81a88a6f28eeb189b889b3
-dist/2025-06-24/rustfmt-nightly-aarch64-apple-darwin.tar.xz=62fbf75889736832087badca386546bce580601d8a396be707ccab1c77fc8ad1
-dist/2025-06-24/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=0b50197c8e1b988d1cf6bbeef055bfdce5b01efc07742ee85221c57b2d70e33e
-dist/2025-06-24/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=c555acf28f160f9b133c4e196305ac9e0f5b528a683690ea6980a457b3cd4184
-dist/2025-06-24/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=54b7acb5fcedd0fb50161acf1977e62904cf55a74f98e8530f64b5459a7f04ec
-dist/2025-06-24/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=a96e42605d11c5220a0de5164f32522c884c61782075933f1e6eaab1bb4a41f4
-dist/2025-06-24/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=d4b7d8e5fac122215f6d75654b9a60ddfd8057818ad5bff945a7823bfa17354e
-dist/2025-06-24/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=8cc5a0760dea509e435c0185f4c5a4a8d64515fb280808d18cc77d96632b4479
-dist/2025-06-24/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=c0bd020fdcc8eed3b34ee7aa12181c56197df339fd84b1cda5386e4848c0b0aa
-dist/2025-06-24/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=eb521c9a78be2c814b76910dfeb8dcf233a9e1076c655f3c682f5b79fd1ec4c6
-dist/2025-06-24/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=34a4b7f51c39e5b41496f085d85396ea3f95384315c0e184dc78da3f75c3478d
-dist/2025-06-24/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=a9da4962599db3fce8d5e31b0aeff681a05198d32838e9844b49de12af88217e
-dist/2025-06-24/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=27dab44d55602c98447d93a9f0e566e8f772c97c8322a7cb54144f9b6b29af71
-dist/2025-06-24/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=1598d5d8612de93539b36e1a421b5f1ce97a71eee8a5a9ee85aa6e8e9d778fca
-dist/2025-06-24/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=a62d2f370fd9aa99152d66c0ce49ed2595f8e48b4ee40a95271bbd7a584410b3
-dist/2025-06-24/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=e0378cd9afc1a9e6b6665b98a3a2c089e42bda56a855cd1d2011c14bc75e6886
-dist/2025-06-24/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=f316d4b45a2d454ca2bac683d470794c80db84fcf6f809c20b11333035d6f2ab
-dist/2025-06-24/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=6e73b85d0fb10b77646db2cdc2ad236a8a5d0ed71761e171b00ddfa6b6d7cd83
-dist/2025-06-24/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=034eb9ed25935694ee0c530bb58bb0dd5586d7361f1f1356fb67af5e5c440c62
-dist/2025-06-24/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=0873543b725aa062f2c6dd00f2be3ea66dad56bfa2a25251f92c0d8b495eb9b7
-dist/2025-06-24/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=7cd21e55b12d13de4f6a7678e89141476dc96523f91622da662672e3b967547a
-dist/2025-06-24/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=08c9a5e50cd50c2a5676ee49fbcb7b2a622c7823dd787f79ab1feee38ade84f9
-dist/2025-06-24/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=3e7ebe2cbd951ab9c9b4863aecaaf18ee09c200a1d58430d1bd6be788ac7c311
-dist/2025-06-24/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=76d79e2f26c19678a8191295563abc34c99ef971fd795cab8b690abb6afcc46a
-dist/2025-06-24/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=7f29b3b39f0d49fc6033006d8ff72fd9bf64ccdb9865f3654d06db46a62170d8
-dist/2025-06-24/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=25e85b3608dd57fb997f58d0bd626d1148eacd51fcc62066c3dae2b4edf475fe
-dist/2025-06-24/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=2c6c869cdd36dbedcf8ec6b803f1cf737c2ef159ab0c7bad57f9fc1a9bbc944f
-dist/2025-06-24/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=2a6135517dea234a8cf1e1bc503133b232f053e6043818ea11a38a9133742a50
-dist/2025-06-24/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=cd9957ba8ceee1cbbfc64c7d336cd14cf86d80d4e2f292300f1693b7f333c8c3
-dist/2025-06-24/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=002a7a3286cb9794d6d9b4a4ad711ddb83cda8acc5150ed82ceedc04861a19a2
-dist/2025-06-24/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=1a905ec7b06ac868f448ebf96c8ace4397e65a040c3c284b37446f95a2004bcc
-dist/2025-06-24/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=2f3ed860d7c5416a8ce8e7a9fbf3435d34653692adc153054af0044a3bc544d7
-dist/2025-06-24/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=f2eaf7ae2de5bc3b1c66944cfe145c5005bbdfaa7f395751863eb62650cf6f80
-dist/2025-06-24/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=4f646fe74c3a155837f2febdc720586a6bd03ebe93b130d042c4061012c36c62
-dist/2025-06-24/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=cfea8bd86d79dd10200c80debd7b0a67c2f9e15aa32bbe293305b4cb1d4c140b
-dist/2025-06-24/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=82dc1b9dcbc2a16948c73aa11fa7faaa1cc156c70811a76c9ae6bae87527cf05
-dist/2025-06-24/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=1c78e4dcda6625502ea55945e60c489afb321c015b4d5bf98f16df36e363c5e1
-dist/2025-06-24/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=90d072b9f5e23252ff98808f878718dc0eafbd2f379c33814cf355bf824b91bf
-dist/2025-06-24/rustfmt-nightly-x86_64-apple-darwin.tar.gz=fbc0a4f9b03caf6cef7b3b44f45e952b5f2386dabe27f6f57bb1d5a07e92b679
-dist/2025-06-24/rustfmt-nightly-x86_64-apple-darwin.tar.xz=334563dd55124add3f08e5ad0360870f7dacf643a2db10842da629e7b82d844b
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-solaris.tar.gz=70a974c74c4bbf14ad52dd91feba8adcc7821e650e78beb46f375fb23519d433
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-solaris.tar.xz=851b15e50d9b02518bd82f4269d80c31eee4f5559a5c871af013272e9f6e68a8
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=5608ac9918b30cf05ad1110a7a2da3f051fb97da630a6ce34ddb02927e6dcff2
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=8fcb4f2159189af9d94253c1b92034f8fd18d2dbe6c2c72b172fefb6acd1bab7
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=e2e85fa9b30cea48a5ed0dbeee8a14dea4c16b31208fb1b884e4c1253bcc20fe
-dist/2025-06-24/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=cf11c5776728edf90ef7fec81f7f46d5edfa4d827629346f1b8cd1e00fb9b1c0
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=5f8befb9ef7640b75d9c29955f3ced2a128015ca1f39bd24aab2ef2587a5fb99
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=2a09a48f979bf762d465704bbb4f90cc1bf6b10a1d8b75434370b38dba91e62d
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=e0be33a6c1272d885939469354e9d8a670a370408c2c3f1b095a9f36de514849
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=9ac7896342c3a2411b3dd68984c6a94d8cec52852c551745c363552e54767fb6
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=4adfe1a8ed77ee7f7aa17f4181e87f59482f7345735c939d181e86870ad4edef
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=df97ab0f9a090b3a01b089ba8b259333c3e0cdc34a2cfb1f91d204a279b60783
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=ec13df06afe80f82ac7af36fb76461712ca6a5993a3935966c9dec9a9af15b74
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=db58fe88b3795306f08afc79b676c92397cbb5f49a934f764eab490826788ff5
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=23f7bd79106676c6a26828e663a51b4c1450fd1097b684735a46ead2ff54a57c
-dist/2025-06-24/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=d294f8ed438c068b6792f7ccdecf9716e08b927249728f4aac7064b983e71e5c
-dist/2025-06-24/rustc-nightly-aarch64-apple-darwin.tar.gz=1f6dfb2fd4ef09e0889589747d239b5e1af57feb859d89efed7d30b9afc3e8e6
-dist/2025-06-24/rustc-nightly-aarch64-apple-darwin.tar.xz=1fcd2e30508b664208c236ff3b522a62c385197c9af4131b060d10b5a5b89d20
-dist/2025-06-24/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=f0ddd8c974d8a0022260a193e16c045334c0526328604a4ad26b9efe6953de4a
-dist/2025-06-24/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=9274d4b17011713f9a7b050e89ef7626b8d24300456463d1c7d7a65f8be54039
-dist/2025-06-24/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=4155841d5101c2f7b65282c4b5b33146acfe1bffcf2c68d48c5b4ca31d73b663
-dist/2025-06-24/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3547deb9ca8fcd638b0c17f9e3848034d4b9dc2a859581932e95344715058b21
-dist/2025-06-24/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=b63dcf52528338728f5a29b51f7f38f99999fec061b2b9bd789e456cff0a16bf
-dist/2025-06-24/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=e77030ec0dfefa9ea571483c10a590c5d58f084fc8ce3e10031ce9cf503e9675
-dist/2025-06-24/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=a1da6251ad4cf9710382bb871d9400c0886fb17b2790477c4c2933c97bd1552e
-dist/2025-06-24/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=96051a8bb8c0fc377d8fe8af861398c39bc21edd6e808977d728eddf6393ab8c
-dist/2025-06-24/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=fcb7eda9e1060cf4c4c702681d0a0ab6680f0e1875a7e0da2bde01f6b018e834
-dist/2025-06-24/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=56217f3b73e8cbae769a0a20d2a01e1f2d474c67bc10f93e1a9f7c2d51da0ac1
-dist/2025-06-24/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c02e586ee5732d8b89f4262333de9444f0cd48b897a51e8767e505abfe54921f
-dist/2025-06-24/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=4d0eda5553deea639d39d2ad663d6f077b14f7216b99268bd787196475fd1205
-dist/2025-06-24/rustc-nightly-i686-pc-windows-gnu.tar.gz=1e9acd43dae9e1a199c96e6842869e1f3418d0167f93f9220fd937ee63363645
-dist/2025-06-24/rustc-nightly-i686-pc-windows-gnu.tar.xz=5e12380c2c8d2ec40ac8e6141c9ef9c9430928fcf2491bb46e27ca6529b7a779
-dist/2025-06-24/rustc-nightly-i686-pc-windows-msvc.tar.gz=fcba4f7b348d06d5ac602111a53de9767d394298eeebde41200780e73bb39c93
-dist/2025-06-24/rustc-nightly-i686-pc-windows-msvc.tar.xz=ce2b140a46faa99a96f9c02fa44481f6414e1d4bed94015dcc773a07b133e39b
-dist/2025-06-24/rustc-nightly-i686-unknown-linux-gnu.tar.gz=eb57e8444762b11f88aac3217807c976a87e22dfdccb790c7ed1c30c445c033f
-dist/2025-06-24/rustc-nightly-i686-unknown-linux-gnu.tar.xz=b0395824f59a07c311ecdef0cd54a2734eb84a7a817561eb157ab66f5b46b9be
-dist/2025-06-24/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=cd512e558d3cb27913cf79a188529d953b770452a3ec11d63c843424ddd04e6b
-dist/2025-06-24/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=8fb1c1c32ccc3b62f100dbfa151c70e86de571adcf215d978e0fbcf80448a555
-dist/2025-06-24/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=ec39e3ed4f93d4ce31c748b2109e921065106ff850540bfbd4584ada5c296b83
-dist/2025-06-24/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=600c2457caf6ae99502e96e2ad6021628611e4feea6e8498178e257fe4e3bf8a
-dist/2025-06-24/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=6a91c5f05a167ffb7c32aa719422e816e592fcbc3f6da1d77e15df1360888133
-dist/2025-06-24/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=b8e935a3715139bc2d5fe89f08c8e2c7bf5e5cbe3ce555e0c6306bd4fc0d5c37
-dist/2025-06-24/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=fc50b819def6bec22245776b01b1332086604a04170951a43713286c88a8ab06
-dist/2025-06-24/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=07c23da71f7330c19cffb16866702341dab46a7cd3151b054a3020e16a72ef70
-dist/2025-06-24/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=b8c5f9a1868f6ef86630eab919aad9a8cbcec274badd85412d7a807d4539b648
-dist/2025-06-24/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=b555f6f3e5340a79766b652c686973d827a5e18676c2204880bfa76bd9b18379
-dist/2025-06-24/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=78c4e13ec693969eef566a69845e167c881a2e3f1c668abe98511dc4e7ca4ce1
-dist/2025-06-24/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=a4d67c535d135fc180a7cda7b012d67ed7b315aea2dacf875ece0d1364a573ff
-dist/2025-06-24/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=dda2348abc72eec12707421751185c6d90e8751aed4e8b36df01becdce35ab24
-dist/2025-06-24/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=03fa26da35f92d2f1833e06da81fb0ccdf60feeab5189ffe789e81afa93fcfbb
-dist/2025-06-24/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=6e12884335ab012c78a4f672e143303cbda142a728a8379eedec97fba76f0f0c
-dist/2025-06-24/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=e235dd111abe60b11ab020618a5eddbcdc105c8ea63f91c886972d6298b38512
-dist/2025-06-24/rustc-nightly-sparcv9-sun-solaris.tar.gz=53fc8dfc78e01dfef45bdb840cfd46acbca64a6177448f47d8fce52db6eef224
-dist/2025-06-24/rustc-nightly-sparcv9-sun-solaris.tar.xz=99eb657c275896295e2dac5868a7209de64ea9edb951a4bbf1336afb105bb6e7
-dist/2025-06-24/rustc-nightly-x86_64-apple-darwin.tar.gz=3d08912e28645fef5177ded3979abd93b8d2c2f1b391035b4709f0411180d772
-dist/2025-06-24/rustc-nightly-x86_64-apple-darwin.tar.xz=ec77aa5e779fa33e21b39501e19c9ae4be2b3fceb31372b571da7e55ed6e5493
-dist/2025-06-24/rustc-nightly-x86_64-pc-solaris.tar.gz=3e6639d90cb9f79d3d7e484f127b9d2074163eb6d6b82ee8d05c025380677afc
-dist/2025-06-24/rustc-nightly-x86_64-pc-solaris.tar.xz=7bc1294b1362773428bdb2604033658af83c9af75a4d986106d950fe2a6e7259
-dist/2025-06-24/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=71d2ae019fb18e7b592a5a89e79256fd6cd77f594a8272a2d906ee0ad6a7c314
-dist/2025-06-24/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=8592859eaf1453b98ff0d66e78bcc4507727df8b74e8019620f51ce61e2f0359
-dist/2025-06-24/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=e85a7fdff5a848371da8ead8aa476e0bb966bbe7fa75f4fadea793a417ee2fd5
-dist/2025-06-24/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=98ec37c80995927851cf2b4a47d520b2ee2a4431b0e31c117bc8df8dba813b15
-dist/2025-06-24/rustc-nightly-x86_64-unknown-freebsd.tar.gz=47885c0006351251d9db998bc8367d4ea59aa33798e35c40aad6dd804b057362
-dist/2025-06-24/rustc-nightly-x86_64-unknown-freebsd.tar.xz=8976ecfc666cdb9624b470e8f6d3fd6231d7e949663bea928775308ae89ae8c3
-dist/2025-06-24/rustc-nightly-x86_64-unknown-illumos.tar.gz=98b8058dbe9a783b4aa73678bb7efda29a5c13eefe332c873d265805eb9c7a4f
-dist/2025-06-24/rustc-nightly-x86_64-unknown-illumos.tar.xz=30abf5c4c71353451a6c23fa02a9160b1d65fb5946e2166a5b3c5c77e9905906
-dist/2025-06-24/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=eeed224afbd20219b4f19c4a31f9cdcf9672af7d20ec3cd688d02764404f7cdc
-dist/2025-06-24/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=01e1f185c4a0c18b256b4d13e1eb8aff312a6969f630ce70411367454642fe4e
-dist/2025-06-24/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4c57c6805d18f1bc53acce957c0b1279a1b0894efcf0f24c744b3765a82c59fd
-dist/2025-06-24/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=3da2e26f0fb0a94e3caac0385c82eab54e553eb9759723dfd601f5dc25a87906
-dist/2025-06-24/rustc-nightly-x86_64-unknown-netbsd.tar.gz=a1b2db0321e9b22c11eb0ae1a6ed052917600bbe18b46bf732fdb20a60cc0950
-dist/2025-06-24/rustc-nightly-x86_64-unknown-netbsd.tar.xz=306d96754bdfdadd4d1c2dd303f5db06f3e405b343210209c256d1b1862d47a5
+dist/2025-08-05/rustc-beta-aarch64-apple-darwin.tar.gz=b9d8f74da46aeadb6c650a4ccfc3c2de08e229e4211a198fa2914103f09f579d
+dist/2025-08-05/rustc-beta-aarch64-apple-darwin.tar.xz=493ed87c65bac5593c104373a3277ddc2330072796704e4b6800c531326da860
+dist/2025-08-05/rustc-beta-aarch64-pc-windows-gnullvm.tar.gz=6c20a3b2e4d3ef9a54b1fe4f50c71895d4d8557d6960f887ef4958c0f2a19eab
+dist/2025-08-05/rustc-beta-aarch64-pc-windows-gnullvm.tar.xz=d6bffc013745c0d69f4cf7ab4f747f8ad885e3b1b77fa56c2e7de8808e278294
+dist/2025-08-05/rustc-beta-aarch64-pc-windows-msvc.tar.gz=3b6bf7e2aff93854346c1d0970cf207c049c17c5ea6ee299dcdb1fd92e996fc0
+dist/2025-08-05/rustc-beta-aarch64-pc-windows-msvc.tar.xz=8241fdc7c673499091700cfcfafe10f3b70bf91918a3b7204a73d2b28445cfa5
+dist/2025-08-05/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=36a093e6c99f227e293ebcaebc89e58166e3da7447d2499069c616610fb4e691
+dist/2025-08-05/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=7cad77f36dcabbe77d603b8b3b4bfa83488a3af2e9b815f698f544de148c77a8
+dist/2025-08-05/rustc-beta-aarch64-unknown-linux-musl.tar.gz=421980aa1ef5467f59c1a8ad43415d69057c9277fdc91d1d5c2b53c246e8bbe9
+dist/2025-08-05/rustc-beta-aarch64-unknown-linux-musl.tar.xz=0ba5b4cd4f5975a58cf86331de5a3c80fb2fd620d50797360a5af4ebf2bba575
+dist/2025-08-05/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=13b3e61ca606bfdf90d46a8873ca4f14fa07ad8bd77364f1a85f557f31ba7299
+dist/2025-08-05/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=f6a1991e55af549d6cd59ddbebb6d2289d90d1e37b2a9449d7831b4c117a54bf
+dist/2025-08-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=a5533df1ae642bcea571aa6c2b5eda16a56c6cd597906081840bb7531f7b02a3
+dist/2025-08-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=2a7187ad6d0215f07d0472880e117556508780e37df6e2a1a7fdbb67fd8dc87e
+dist/2025-08-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=3ae6e7d83ae3e1c5c8030ba93b9103addaf11f0f8807f1fbf813305d8e6a9188
+dist/2025-08-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=324d6de1a8e4d9c1dd13cc86665fd06cb167d4a3ea55607cd5353300733f480e
+dist/2025-08-05/rustc-beta-i686-pc-windows-gnu.tar.gz=0bc4b50638818008e054af245d4e987ce5e55fdc56e19d31c18e8c0165f860ab
+dist/2025-08-05/rustc-beta-i686-pc-windows-gnu.tar.xz=b0e5343207a9684d5efe81e536d23135df07bebd869dcad69c632811e1e37137
+dist/2025-08-05/rustc-beta-i686-pc-windows-msvc.tar.gz=c3231335a50402989d4e08857fd7194a3fe5384d2aa34153a25a3f2955a942ef
+dist/2025-08-05/rustc-beta-i686-pc-windows-msvc.tar.xz=be578fcbfe32e40fd9688e618927ddcce88e7e08a279778d4c3399eb46e8ae29
+dist/2025-08-05/rustc-beta-i686-unknown-linux-gnu.tar.gz=96b2cdda499b63aadb76b37a4895623a4806c5c8db8f6edeaeb1b812d337192f
+dist/2025-08-05/rustc-beta-i686-unknown-linux-gnu.tar.xz=f6496eabe0efcc09c7a4994cc4825e9c3e494c8ca7679cfcbd38a699438e1b74
+dist/2025-08-05/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=3403d7be2f49387149ce075b427f8eaa306066db9fd4ec69de61dc01f6834037
+dist/2025-08-05/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8cb3a329ef3632afc1f709b9f9b99a2ab7f5c18590590ddacf64f1b3e5a3ff69
+dist/2025-08-05/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=9485ce37e99a6a53b5521683bec65d015a730a41c4c3f3baa19226edd211fc39
+dist/2025-08-05/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=450d91ad61a23f69560e53c7001aec047bd17fb4831bafb97e7226162bb3c0f4
+dist/2025-08-05/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=dc9ff117a7dd3e685c634e8668d78022f66f6e58dc449fbe5f398688ed2dae0a
+dist/2025-08-05/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=7dbc936f94d531040601d6fc02d9db87335a1b7927637494c9e208a43f012010
+dist/2025-08-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=4a68557cf53063817ee651f5838ad2c3de93a647b9002fe3c82f0372cbd71708
+dist/2025-08-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=f5ae9c4ba17d2941e8fa947d9712a8db8dbbdecbcfa4330988d02b9299fbc814
+dist/2025-08-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=ad33c48172c3b9abbd95b9dd3c1d38d5f6bc25fe84b95e492b6cdad27ef1bf19
+dist/2025-08-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=89d40fb02cded4e8d9b3e177f07e1b984481d493015a2532dfdb5b8aaf5ffa94
+dist/2025-08-05/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=a5ab7a321363502609a4ec5464be96629c693395503c8ce285990db3c556a775
+dist/2025-08-05/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=7e3b5afc7858857d5840bd6e788fd88449555e2fbe4c9a206ee3552e61dd79b0
+dist/2025-08-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=fde633217cf77d6fc6f901d84619f681a1fd1e42be75960809bab4806528a451
+dist/2025-08-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=69541c68f31a401229d770ef2ea6d032104fe928db845eae23f04c40db021a8d
+dist/2025-08-05/rustc-beta-s390x-unknown-linux-gnu.tar.gz=dc257bbab4790dbc3f9df70853eadce198dd5f6f47c8e830254ee2b21c6c79a3
+dist/2025-08-05/rustc-beta-s390x-unknown-linux-gnu.tar.xz=d5a9d5c555241b231eacc0584db0b540ee2982e8bd66cf8568064aab4beb0c94
+dist/2025-08-05/rustc-beta-sparcv9-sun-solaris.tar.gz=96b25f8ce6db2f9d9b7e8da75839d1bd4c97011bebd2544633ab2061e4460bb3
+dist/2025-08-05/rustc-beta-sparcv9-sun-solaris.tar.xz=88438d143441da62bf5415857aab3490697f7f413b7de41cd113bac1480ea7de
+dist/2025-08-05/rustc-beta-x86_64-apple-darwin.tar.gz=f59175ef402489c1dd2f6a8984ecb66314240a8e4f7c55e5d92017fc025fa4ee
+dist/2025-08-05/rustc-beta-x86_64-apple-darwin.tar.xz=21de96e49395252e6eb5b175ee794acad78ccd4ac081303a8da7ec84bf2b6ab1
+dist/2025-08-05/rustc-beta-x86_64-pc-solaris.tar.gz=164a9b76347131d78fb81519627ab50f13a313d8da13d09f7fa479a41c519458
+dist/2025-08-05/rustc-beta-x86_64-pc-solaris.tar.xz=0f91f1f4b8880944341d82894b830a70f8a60837687829e0ab9626f3281ddd1b
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-gnu.tar.gz=634711ae22708a5ae57bb2022fd22257664a8510b59975f4b4ad4b9a8acf475b
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-gnu.tar.xz=b72c0d3f5800e92b91d1361e52b28ff622aeb1f1cbdff2efd22c2f2a3315dd68
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-gnullvm.tar.gz=668f3a8b48092721bb6e1a01440776d6b906850a11e1bcc37a50bb13ef8d7b04
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-gnullvm.tar.xz=e06a183829e09448e76daaf8c317b52d11fac7d16ad191ef61b8f7a806eb9414
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-msvc.tar.gz=564849501d1e41fe776f5443b87c9500621adef97eff05d2c03d539ea3c886da
+dist/2025-08-05/rustc-beta-x86_64-pc-windows-msvc.tar.xz=6a1c1cc47c0e8b6aaad215d4d4e8b770b96336e9f2a0317fcf0511b662966bfd
+dist/2025-08-05/rustc-beta-x86_64-unknown-freebsd.tar.gz=560bcc4d150f4e22f5598d61fce86c9baeda1b57bda837270f7cac78cfc12b19
+dist/2025-08-05/rustc-beta-x86_64-unknown-freebsd.tar.xz=cdfe207645068b4659b0f979cae177723c5f211084f45ae9180b2d93ee83fce6
+dist/2025-08-05/rustc-beta-x86_64-unknown-illumos.tar.gz=5a362ca0c686b0e0666824df3f304ec49d7d419abb08473fece69d41e96ee625
+dist/2025-08-05/rustc-beta-x86_64-unknown-illumos.tar.xz=fb4e7b12b5223545f6fd57754744f03dd6807b6801e97f9f0fe07bc371efed62
+dist/2025-08-05/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=74225a1889120c0174a056e7ca7656f38e8788137ee3d29df857567ae0605692
+dist/2025-08-05/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=2d37542e88f84a0501841e12865262142fec0efef9ca729d26a3c333f16e465d
+dist/2025-08-05/rustc-beta-x86_64-unknown-linux-musl.tar.gz=156eabc89e1ee9558b9de6f60b1bc47c81ab33ae20fa946c4ad4e32b7f30c221
+dist/2025-08-05/rustc-beta-x86_64-unknown-linux-musl.tar.xz=0cf9e649b9020fcfd25282ae1edb1ac59560b7d6d0f79ff7ff3b62871ff25d86
+dist/2025-08-05/rustc-beta-x86_64-unknown-netbsd.tar.gz=8db86a95b22efc2ff2f344e301171813375ccfd2aacad61d3aa84a63f573647a
+dist/2025-08-05/rustc-beta-x86_64-unknown-netbsd.tar.xz=68c10c6431b4433d4de5d24a9bb6ebabe99769b077cdd80ab5e0ee67a273035e
+dist/2025-08-05/rust-std-beta-aarch64-apple-darwin.tar.gz=872e61e6d6915c02de0b9437b910f6f37f5e11c83347bbe2284a59c31aa27ac3
+dist/2025-08-05/rust-std-beta-aarch64-apple-darwin.tar.xz=748516af852836f06efa927cc96bdd2ad6b012d0262e87bdec97a112212cc24a
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios.tar.gz=2c1cf24819ec790d124c7ace59c12a903250eefdad6362b40c779a97b732459e
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios.tar.xz=b2fd6df9653b6c0bc13d4331355b3b9a4756886ba46d6c744687bf7bbd8e4630
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=c266b75c66ea17b174ce8a746bbad78bca58bd72c3cdda603f20a868f9b3b00c
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=da5558b25c82a5fc1b66786b035212c5d0df2d4124da3e581e15636f29547dd0
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios-sim.tar.gz=8441032f41e142faebe78e84501344180447121602a2000d1310d7a716cf3695
+dist/2025-08-05/rust-std-beta-aarch64-apple-ios-sim.tar.xz=48713adfa5605addd97e13312f6bc4cf103c06623f67705732684b51d0bed8b1
+dist/2025-08-05/rust-std-beta-aarch64-linux-android.tar.gz=1eb2bbc5fac670aa5867546f1caf1378591d5c0d3a3800ca1dd052645fea0cd6
+dist/2025-08-05/rust-std-beta-aarch64-linux-android.tar.xz=ae5e8aedcc5c8bf719e8ed788d52cc69daf64dfcf878e8497b45454c1c582c56
+dist/2025-08-05/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=bedf5d7663acb4e1afed9dea4b5b8e9b7f0e0dd68e311d3597819ddd028576f7
+dist/2025-08-05/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=e19fd9dc6d9e774e30a9e4a16ac5d6d1fd3300eb880c09f6b61cc63d52370629
+dist/2025-08-05/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=8ad111b1e8e19fdc5bd33d82a1f6d88b9c1809e27531af9d9fed2e37f75edeb4
+dist/2025-08-05/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=332976524e42b4d7b2763a28cae3ebbc3eec03465c098df26e81242294277de4
+dist/2025-08-05/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=92f4737a1775c1fed9311b8949950c6606ca34d272f787d222923555fb69f98b
+dist/2025-08-05/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=2f1ebaa974dc3c6b39c43e38cf6d9f5c6fba0d46229a0423be676d817905850c
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=798dafd6f581f367dfed9763b62b35e77466f87ae8252a52f503f1c1bf58f1a5
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c4434727604a2773f73e8919a6e967c7c487d75684514cacbe59fb2d6a5f0d29
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=c48d4e44b0e94f341e7ab2f9d47b08280930152a53dff20d6c9140739fbd2898
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=8cac54d6a39c13dd0f38fde523a852c5db7f61a7f05b3e3ad0f78c7f59513d02
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=5c3d7ea7ac6ab60311fb49c5a2f04a92266bc8a675d7f333219177a91b400f9b
+dist/2025-08-05/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=f1f9f8a71fc5903bf720d39bedaadab16363b37f9e99817d7cf27b7122ad1ad0
+dist/2025-08-05/rust-std-beta-aarch64-unknown-none.tar.gz=ceffb671e87556b304e63cf01572e1cad8c8cfa0b33ccd1a373b033c60696376
+dist/2025-08-05/rust-std-beta-aarch64-unknown-none.tar.xz=a9a9b17f2b4fdf45f46359726e0c28f6a1289a7abf81fdbe1ae180b2f550aa60
+dist/2025-08-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=9f6f6a121e3b19b7b3b2c85dcd13544c12af18cc5544403e29ea8bbd5b13fecc
+dist/2025-08-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=5b0f0059dd5d837fad74aaf2971fb135229b030a832268106be512557cc7a611
+dist/2025-08-05/rust-std-beta-aarch64-unknown-uefi.tar.gz=67166c7d6d7210ca97c3610abfa126234653d0e26658bbea64d574852fad04fe
+dist/2025-08-05/rust-std-beta-aarch64-unknown-uefi.tar.xz=05f72e7c0ebbf7b41bf3e773bbbc073ca9c71417a80dec8f3916dafbe0cdcf7b
+dist/2025-08-05/rust-std-beta-arm-linux-androideabi.tar.gz=bdf103a29035659972f35bb9060ba8df5ca9b7b068e3c094d758331a5e667144
+dist/2025-08-05/rust-std-beta-arm-linux-androideabi.tar.xz=8fa8b6994b4e04fec77a6657db0fde4e4cb9336466ce0c4f3e2b154709969c93
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4298510905c958e45291c2fbc4c54bfed9fdafbd48636896fe00a73e94f700ba
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=79e0e393f5286429755faee738ed110fb1cc51b83aec3c94194e903f0b938d73
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=37278a621e2449b9030045c174c71f3ddf74e70b49b5f247c36fea1b1654979f
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=3ac094e855f7593a22a56ec40923384a0e25265645d05b2a46dde2612d9c6cf9
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=b5bc7d83a3c59764cdc169ae349e01cd052b8ab054eb13b4f2a1cd02ddd7fd6c
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=2f8558fee897543da620531e500f3a73c5aac4ea815b7bd418945103dedde530
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=2e812427b5169e7de22b720776208ae92f9075c5509f6b9ad8666b9866232735
+dist/2025-08-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=e544363209177357386f220d6c4101b1d86d84c03e51254ff459ca42ef187107
+dist/2025-08-05/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=778c947235bb0023ca26dc0592e4d3cb9ad9665c3316d57822c173ba2b5e231e
+dist/2025-08-05/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=3a5bf7620e1b24e1f72968f5cc28cc58acc9b5739f2c08f5c4b9e449d8c551a1
+dist/2025-08-05/rust-std-beta-armebv7r-none-eabi.tar.gz=fcace82dc77156a6e7c658fc5abe4992075cfe822fb18a1edfca1967102a6adc
+dist/2025-08-05/rust-std-beta-armebv7r-none-eabi.tar.xz=9616372693902e89b55de55b62009a59baccb11ccb63710a475856deca70655c
+dist/2025-08-05/rust-std-beta-armebv7r-none-eabihf.tar.gz=2c596de7d22a4762908676d4e048f5075cbf2d66c5f7a03afb96e709f2d080ca
+dist/2025-08-05/rust-std-beta-armebv7r-none-eabihf.tar.xz=b1ff9e3fe11acc22fa5ad46530dff62bfceac9df6fcbd3da7999535a00dd2e3e
+dist/2025-08-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=e033e4bfc11a5bcb7f0645426fac899f7d071236a228300ca2022935997b17fd
+dist/2025-08-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=919587b40e2bc6c6e8f496244c357c04d5e53b8adb9b3f274432943fd789a1a4
+dist/2025-08-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=392a1f0528e4b783e5fd0be74efbec58eb3b0ebd69c3855675301ebf96b76c4a
+dist/2025-08-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=183144eb89cc1a035c04d50c4060e159ca5099fec71f4f25801a924fa013d04a
+dist/2025-08-05/rust-std-beta-armv7-linux-androideabi.tar.gz=f968b761773b76f151b39dce0f3757f59eee2d8b70373d1419e0986429885d7d
+dist/2025-08-05/rust-std-beta-armv7-linux-androideabi.tar.xz=fecda678541a151b76f3874e710e875a662a9165eaf1cf12b081ea55ea18a38b
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=300d7e8adaad86ddeff643109d0c83a87e41a056171f9d48b0b6108719003325
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=acb8f61c97efae6e95aaabe1cab1300bc3cc3a1dc2066c7e2376ad6a9994971c
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=5e90333cb68f3161f8cb30e69d4ebe46f6653998651c72a87a795ab02c11dade
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=355bc516a7a6454eaacc66eadaa4d640cb3ffc7b5400a01bb4bdccf4470ae650
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=8daa2c4c4dd9e8a1b9ee8a60f2cab0dab81aaf1e7a9d732093979ccdeac8bf60
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=52b78d85f8e9e19da83504bb523aecf7b641d15c1de2f9b988bedf52912636d4
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=c63000f15b52881c20f40cf1468afd4f3a2a6a84e944357fe6532c7d0e281b3a
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=53fc3486e4d805386c1ac4d6a1007a9b5461ae606c9c820951b720b45dc8f35c
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=315fc371ac2cddeb65c87bd50369e28247c16ca55fdab527e88899e01adc9efe
+dist/2025-08-05/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=d7999aff0a39c63709977f5c18d79b575f8bfb467fbacf4f1b41cd26b52a6701
+dist/2025-08-05/rust-std-beta-armv7a-none-eabi.tar.gz=0707721586e8929811c2904e4136d31f5c415e3f00bfa88dbb920360aa9deea9
+dist/2025-08-05/rust-std-beta-armv7a-none-eabi.tar.xz=bedfd1a808f758f5088ea0fcb746d3ccf11730945e2b07220e93829c0d5c472a
+dist/2025-08-05/rust-std-beta-armv7r-none-eabi.tar.gz=315fadb161b3be540b7a276ebe15b1f8d4bdf73b46c1633e39f698014aca8eb1
+dist/2025-08-05/rust-std-beta-armv7r-none-eabi.tar.xz=4bc2fcd9dee2ee44914da0e6af3763c7ddcbe3ebd9fb20c1d552a0226cd877d7
+dist/2025-08-05/rust-std-beta-armv7r-none-eabihf.tar.gz=9c8be30130709ff94a9718091559a752530f0eeb21be80fc3cca0665e85ae0dc
+dist/2025-08-05/rust-std-beta-armv7r-none-eabihf.tar.xz=f0dd0bd30ed70c3a022016d8bbed54a6e942571f2e4c773bd8b4198d7dccdb5c
+dist/2025-08-05/rust-std-beta-i586-unknown-linux-gnu.tar.gz=ca6c3b8af1c44deaf7dce9e8d4c8786a5801226b30beaa646067d393eeaa0ee8
+dist/2025-08-05/rust-std-beta-i586-unknown-linux-gnu.tar.xz=4e96f0e5f2e3eda60ca2b6d9ce234ae74c5eb2412a7e2c0c571eaf792dca6e28
+dist/2025-08-05/rust-std-beta-i586-unknown-linux-musl.tar.gz=60c736e3ac2aa5b9ceedcd73e39efa12bc9b889ef85f548170f80fbf2b05dfa0
+dist/2025-08-05/rust-std-beta-i586-unknown-linux-musl.tar.xz=fe636d893e38c32a163a88ece160d5b5ea61a3fa63463d4e4f425d229c2927f1
+dist/2025-08-05/rust-std-beta-i686-linux-android.tar.gz=9e62d61041187a91b74c81fe77cd6802a7e38c5a535412c71850426f6a48f37c
+dist/2025-08-05/rust-std-beta-i686-linux-android.tar.xz=862d3d5442fb011b917f565aaadb201c22e7b2ecd6a68c0c410b3335741c1c22
+dist/2025-08-05/rust-std-beta-i686-pc-windows-gnu.tar.gz=05a8da51c477e2c2ce4ea12d41c8afaaf0d226a6b933b6c55fd3584b39103366
+dist/2025-08-05/rust-std-beta-i686-pc-windows-gnu.tar.xz=cf15b3d2011ceb57064d0b2285defee7df8628c3bf2b95f7f2ac92a449546d4f
+dist/2025-08-05/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=fe11b777eae25d823f40352e47272222c2de8edc2d271eb4f6e7ff508efa198d
+dist/2025-08-05/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a7bb6f223e3542e613eaa7f2b9d9974be71cd2debf8426faa50cfb63fde681fd
+dist/2025-08-05/rust-std-beta-i686-pc-windows-msvc.tar.gz=5fbd709698d80b3227a8bc6cbecfc597e99dede3824c751e1d166cac2c5862dc
+dist/2025-08-05/rust-std-beta-i686-pc-windows-msvc.tar.xz=92fd2a6a5dbe53f68e9ba3ce40cd3beea95ba9d6a2f1293f7f3d917f34739a66
+dist/2025-08-05/rust-std-beta-i686-unknown-freebsd.tar.gz=182acad6cea45855f66646d437ee44ddb1f85c2c998cc5c7a4bbb025ca0d9da9
+dist/2025-08-05/rust-std-beta-i686-unknown-freebsd.tar.xz=53f8bfaabff1dbc47929a99a92025a31c1e272bf6a8091c4f95d33557dfe9ea1
+dist/2025-08-05/rust-std-beta-i686-unknown-linux-gnu.tar.gz=b80dd4e77c56256f7a7f837bf84129d19e1a4aa08a0ca7e2881402371a7e4395
+dist/2025-08-05/rust-std-beta-i686-unknown-linux-gnu.tar.xz=52efb657f28303b0747cf281c972653abfbeb4bf6d0b841f8bbab7f08c5d7310
+dist/2025-08-05/rust-std-beta-i686-unknown-linux-musl.tar.gz=323abc9766231dca10c225b3ec567c694c0ff6f6eddcc30d728a0f08aa6d2186
+dist/2025-08-05/rust-std-beta-i686-unknown-linux-musl.tar.xz=8998ce49f1be28bcd837831f1d7b79b0b339bc74ced42adb6d997ed016e90e88
+dist/2025-08-05/rust-std-beta-i686-unknown-uefi.tar.gz=07261ce98c95839b8714f40e07cbffa32c10fc7c59394dc87b07e144564c5fef
+dist/2025-08-05/rust-std-beta-i686-unknown-uefi.tar.xz=fb6eb023b9722a44e63bcd48fd88c61cf41453842a211107c84039c6883409e5
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=d0a52888f5ef3107ecdbf28b918eb516a9176ae8695079a81a22d1b7ca0e29bd
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c14a477558a6c924e05e1b58bd9df60f5e4966c7f0da294dd38e3bd89c1dc5f6
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=bbb93219393948d055df44edcdfff4b03ca251205c545d6f1bd53ade5f314d52
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=48b437a8afe240828c0377a6baa276500f125661f1bc888ebd1ea546f0497f4a
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-none.tar.gz=fcec6b60a1a22dcd04b8409d38103496d76bb4297ded9f1f092743bd05f0bd54
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-none.tar.xz=2f4aacb734b5a1dd522b4836035ab213db675508b9ff9a1bdc0c2df3ea9d39d1
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=aad8445e9a5deb4a466ebed84cab101bbe8ef49530315c0349d93e2062ae65a8
+dist/2025-08-05/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=906e1cbd1e3b22eb5c378417646baf18b00acb274ee4198ea59ea356f4f1a0da
+dist/2025-08-05/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=b0d7e8daae2eff0c660b6e01bc76258550b9bfbdbf95c104019db7c797339ef5
+dist/2025-08-05/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=c0bffdbb4de90486cad1a26df997006c142f1acc7ed39419975c10b0d09c6217
+dist/2025-08-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=3c845cade37fe2b1cfe3087c69f9ecb3e0eec32d2558701c677d4c21ea9e08db
+dist/2025-08-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=15830d827258f6c3386fa09da66e06ff0460098b46432e28b4e96bd36d61e787
+dist/2025-08-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=4b63d9260253f1d3a0168ed367792284584b87aa936fc76262e9fe0ad83c7fa1
+dist/2025-08-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=dfba70ad94524437fc8ec5e4684239eceb76678112776915f02502b80cb0afac
+dist/2025-08-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=3d96bebe611a0167a43060312cbfa2fe4000b9949772ee44ffd27226acd006c8
+dist/2025-08-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=44e95c2756f52129b8bd21d7d4ad7ec8e05e43192f3bc894cba4a371b579a6d8
+dist/2025-08-05/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=ca5b7c47b63fa8e005078cb73d111462c438b764909ca106933837ac93d5780f
+dist/2025-08-05/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=b102756451c18003ad1b132d25d333ed1a0e4959b87d2904a6e407fc02a7e422
+dist/2025-08-05/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=a592e995b40d3b1eb69cb1f7cd3c100713ea092742ab6ec5769e8df8551ffa16
+dist/2025-08-05/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=af9cd91be3d667cf31b535862882537a406f49932f58308f283228b20fc7bd76
+dist/2025-08-05/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=bf9e9d0f8c4ce8041c6e628e1b637ac0cb316f865f97a43cf2bf522e255c5ec1
+dist/2025-08-05/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=c3e56d71c1586559212f701508ee94f0bfa7801e7d2fdc62c062dcce8a0d040d
+dist/2025-08-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=068023ed1f1dea01f2523f3b2b9ef41b22a301ceafa0526ebaa757481d14408a
+dist/2025-08-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=1e3db6625ebb12a8c735cf4e8658a33bac7bca461de1e516860843d50027ee7d
+dist/2025-08-05/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=aeb986eef375fa1ebb179668c6778c587d1af8b9e1ff50e5b56f9a3b48f1d8df
+dist/2025-08-05/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=45d314189b9327645f6490628157fce32b7b59eccdf57676be0c31e1247f5385
+dist/2025-08-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=82d6e6549c80e62d392654693a28528f2ea540652f3ec0810b6646968cae6509
+dist/2025-08-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=805ffe0a6dfbc886f0ba93ac9ce796c110ea6d0a64b2d6209cdadd56cd2a570f
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=941c683ef7d013166c7f3439ee1229f80a367405f55bab9072dd12725364db6b
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=8b666222443b3954a7550b14ef919b7ab038e6a4a2355386e42c9acbe28f2024
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=80f740bd004b98d5c090fe280ef5e372e4bff7a34dc2ba4940204cf02f50bb93
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=b69ad00f5d60c63fa6d7b32c4d7006d195540d902f8390754c7db92a9221973d
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=ed52f0f9bac7b9d7ec49226eea471e44fecf0416608a5b169d35b12d009e9c1b
+dist/2025-08-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d4dc1b096b26814f14e1e23717cef10f3f63cdc6902e345916e015a99851cb69
+dist/2025-08-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=aa1de02a79f16bb4affb50c3ba0e719352c9925fc57f22f989eed3f7df1a8e5c
+dist/2025-08-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=a36e2749e118f995417f0de9c9835db4b36f8ed6d76d8805510853984f648c5b
+dist/2025-08-05/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=32e6e3672d3c379a1defb6c661eca6f2ce342784feaceafec004bdaa89a0b226
+dist/2025-08-05/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=a449f0392193ab8a48a30b0a8c0c57b0a02747ae8302d08b3be89d475f1b8291
+dist/2025-08-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=a4e0901c13d3c534e176fdf824a97e5a6ca66a198b73a132b957d41b1f198261
+dist/2025-08-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=64720eab59f7c958aadd360b8e2dc5696760d62e9f5f44daba890fc55a4fb6a1
+dist/2025-08-05/rust-std-beta-sparcv9-sun-solaris.tar.gz=8d5d3be06cfe5431b9a8e965fe06837efe531c365e8d46ee8cdc8e9da19099f0
+dist/2025-08-05/rust-std-beta-sparcv9-sun-solaris.tar.xz=913d7fc4aa75ac2175aa52891f9086d48065d96007885e0caf5feb628953a86d
+dist/2025-08-05/rust-std-beta-thumbv6m-none-eabi.tar.gz=ca59366093c472f19381fdc71aacf6b3d659750a8a3bd8894191a42c8c3b82f9
+dist/2025-08-05/rust-std-beta-thumbv6m-none-eabi.tar.xz=e16dc610520f4748ffca99b235e58a544e7f97ca4cf99cbebbeb106ed4acffd1
+dist/2025-08-05/rust-std-beta-thumbv7em-none-eabi.tar.gz=08a281c1bd56149ebd05531fe405a621383ad440fcf273fec04e0792f325d669
+dist/2025-08-05/rust-std-beta-thumbv7em-none-eabi.tar.xz=a9f7eadfa375061835f139bbb870a5692b727de8a85fb8177d8fabd0588e28cd
+dist/2025-08-05/rust-std-beta-thumbv7em-none-eabihf.tar.gz=f996d8b1aae894af11407ac90c277e161acd58378307548ffaa2fa0a4314f3d7
+dist/2025-08-05/rust-std-beta-thumbv7em-none-eabihf.tar.xz=48b9e7d257ad1fac0b23b3a7d6b3ae8afb5dd19db7b5dd2a59ddfe51364db72f
+dist/2025-08-05/rust-std-beta-thumbv7m-none-eabi.tar.gz=1061c6b8794aa4e1f66ff17d91934bb9711c6064362cca7bca1d7cdd4f9189cb
+dist/2025-08-05/rust-std-beta-thumbv7m-none-eabi.tar.xz=974b1078724ac06757d7899fde62f623e61c86ac0853cdbf02a252b13383e55a
+dist/2025-08-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=a4fd4047a744bea871a54af311f27a08b5f7c8f04e5e62f7abf292689378ab4f
+dist/2025-08-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=19c31d2a0982689228eb58522ac7610d33cfcc1b5f72ee2e41e218695a49d09d
+dist/2025-08-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=8b5e150d6950866734b025e58b3714c4acfe631785fc464e6fe3cbedd98709d0
+dist/2025-08-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=23ca585e084fb548488e17adaea92e16ac98340fe146073046d1bfbe6faa325f
+dist/2025-08-05/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=d31bcb162cd2ee40a69acb2c201c07c233b8c2710bc07ad322263121f0d422db
+dist/2025-08-05/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=67354653ab11222806f4a688c11be6dc80468785e14a8b58f2285a695c53c5a2
+dist/2025-08-05/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=ad61d8510d82ca1094a893879d7148446e2880dd1d172b9e8a420772b0b4611b
+dist/2025-08-05/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=5c1ddf66949a40265effbc76ac3da59efb1bb3349dbe2a8037b8215375647fdb
+dist/2025-08-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=4895c9a6659e831cdacd314ff2ca4c968fd368c6bf9308f334468cb07892ae56
+dist/2025-08-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=f64a05715457288b36dd16fcbbdd91816829b889047c277841f3f4972bcc6076
+dist/2025-08-05/rust-std-beta-wasm32-unknown-emscripten.tar.gz=3b144570ddc44868a6609f921028b23f994de337c54a96fccaf976abe4e2ceff
+dist/2025-08-05/rust-std-beta-wasm32-unknown-emscripten.tar.xz=355a1bc09dd4163a416cb78e55ec998e95b8acbb9b072dbd3a8e34f5e95d3378
+dist/2025-08-05/rust-std-beta-wasm32-unknown-unknown.tar.gz=52213b11d29f02d4531495c9d35ee7022ef6b8400a8386b8728156b33d2a9eed
+dist/2025-08-05/rust-std-beta-wasm32-unknown-unknown.tar.xz=1f282c355a1499fc2a212705700fbb8de7e568dbdc5d43d3c895af86fe9f735b
+dist/2025-08-05/rust-std-beta-wasm32-wasip1.tar.gz=f40da6445acb1e854625a02b1078f670874e75d763168430d0ca17ef3b9bae26
+dist/2025-08-05/rust-std-beta-wasm32-wasip1.tar.xz=a0e59495bacc1bceaeec940273fcc6d1505c283de9e2a60ee7d492f2a7efec3d
+dist/2025-08-05/rust-std-beta-wasm32-wasip1-threads.tar.gz=4b4eb08ab33ff2a300828c65a9636f32428dfec784bf115aa53856b5336d61d5
+dist/2025-08-05/rust-std-beta-wasm32-wasip1-threads.tar.xz=54ae55557d66f922112a42aa2c296841f5919907ccd81354f0dbe1b0517867f8
+dist/2025-08-05/rust-std-beta-wasm32-wasip2.tar.gz=b625337e6180ec57abbed063de5bf384949254c46a5fbbb12804a3dbd0d1c3a6
+dist/2025-08-05/rust-std-beta-wasm32-wasip2.tar.xz=5a098a042f5586e7e1b7444bf64edf3dcc535d75226fa44be420c0d42b90c25c
+dist/2025-08-05/rust-std-beta-wasm32v1-none.tar.gz=b11ed27b745437b39ea9699f7fd5413bdb25019720569b9940f1cbac4849344c
+dist/2025-08-05/rust-std-beta-wasm32v1-none.tar.xz=3dd3f07214429f36a088a89c3de7404659d1b584895ff5b7938845fd4a669f27
+dist/2025-08-05/rust-std-beta-x86_64-apple-darwin.tar.gz=14522f13786b81727646acfcb18c81b3f78b24bf522ebaf65adba416971d9939
+dist/2025-08-05/rust-std-beta-x86_64-apple-darwin.tar.xz=b78a1df21a97c25d9977a69bf778190fbf34947c6837f895aeeb53c870083438
+dist/2025-08-05/rust-std-beta-x86_64-apple-ios.tar.gz=a5d57bef3b09c4a4e6789d756cbec9e9459261ab70c94a406d4519eb2da992ec
+dist/2025-08-05/rust-std-beta-x86_64-apple-ios.tar.xz=1b461aaf03e808d26bcae49417f04b71ad1432f266f0b25b3d6b26a67b7f8953
+dist/2025-08-05/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=6c7a3326abd3fb7c878af095699164237f97ce5827bd428d8aad5c9818b2098c
+dist/2025-08-05/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=427684c9613ce04737837a594987bb1eb81d1d3f5ea2a1b19c2b76b3be32ab62
+dist/2025-08-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=2e10607e6eb7fb3168fe593f1d260b52ac578d590cc6788555346cf9bac9f586
+dist/2025-08-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=256331077a036bfed1650177cd1a886aeb4ce9aa9ce2a35f5450767f5e06aee6
+dist/2025-08-05/rust-std-beta-x86_64-linux-android.tar.gz=b5943cc4d10bf039d9b52e56713a99e8edb21d9de3655450d16c557c9013f47e
+dist/2025-08-05/rust-std-beta-x86_64-linux-android.tar.xz=ceeb89fa082b98c8d50c043cfd2e4bb8ac1d98943859a75d74a555ffda8d0a5d
+dist/2025-08-05/rust-std-beta-x86_64-pc-solaris.tar.gz=98d9d51da4b74a2a1899be7f0dd8d3c0f980fb4ce96fddd1c2dedb76e174984b
+dist/2025-08-05/rust-std-beta-x86_64-pc-solaris.tar.xz=0fed1f0452475bf10d3ec0bfef12e9fe05bb117910d871f4099bdd4ca947d74b
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=f458eab66adc91aba026a434cab47bbbd98a9d5e7d0f5a1a1979e0e6a89c8e7e
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=bfdc3bb5b66a525281236b01513f49d96d644e4cd62ce89eb59a8179fe4707b0
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=b543f21106bc3a72d31a5c49118553187cbb0d2e630ea943aa97d3ae5bb4c40f
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=9056c113ee03defb6cd33acbed9829712b57ef3606623169d28416be4110a31a
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=c66ff2e88c79f3fe574f9ef7822d5d2e6f73efe3ebe67c6bd35096622b668d1c
+dist/2025-08-05/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=45765252e930a96badbf06eb04ec092bb989c0ce2067aaab52b7ddc72ea511b8
+dist/2025-08-05/rust-std-beta-x86_64-unknown-freebsd.tar.gz=9b3d68e86e0ce6a484bf615313f98bd289db73899a55cecfa5b7955b4b0878f4
+dist/2025-08-05/rust-std-beta-x86_64-unknown-freebsd.tar.xz=bd48292b8582167a5e89ebe521c9754495403968c184b925df8b2ec1da344fc3
+dist/2025-08-05/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b4c6c046299391beb2f50eff198f4c9b6571b6c1748dd621bdd154694fffce3a
+dist/2025-08-05/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=a30857c8f066191b64d7b52378fae8790814a251ca452c80710bd9a49c5c0c85
+dist/2025-08-05/rust-std-beta-x86_64-unknown-illumos.tar.gz=1ee4b264021b510342c2ed96da0dacf5cf1704874de3bf9380642433defb3e0a
+dist/2025-08-05/rust-std-beta-x86_64-unknown-illumos.tar.xz=ca431d4426cfba2efd408b8822f9aeb0961d81373c6154a0b7eeb957abebc33b
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=ebba9fa476d5b0a42054a6b6ca51526efd7c2cf5ac34eb8af119bfa69f3f0a5c
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d4498920cce484a8b3a5cdf8ee856d80cf1379f9782169340dfff2597b530598
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=20c37745f3ee13c2c81dfc77a80919cc0448180f6be0be56d7fb5239e5651294
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=dd319a6c381b372ba230d86bd07a089cd2431656c7c765f029e8e10d60bbd778
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=d0c20b13113eb62c9a78a796418386d0352f4221095de272018af6d5ec6bd9f1
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=d0e1001e8e5af571f0fd53115ec873091a33e4943dd27a16ccd74dcd8c71abce
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=4be537d5fb6c0d867a131539ef4b0872f9f6d175ba0517fed50b1d463c615157
+dist/2025-08-05/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=ca034c852a4c9099a062f55c5e479bd700f2ffd89a3b2c2c7354df54e41057a8
+dist/2025-08-05/rust-std-beta-x86_64-unknown-netbsd.tar.gz=11b5a73da1f560c218cecf9a71d6b2173df1fbe276e63e20e1e85f2dc48579bf
+dist/2025-08-05/rust-std-beta-x86_64-unknown-netbsd.tar.xz=2de6a8850076e9c1edd8aa3e13902ebbc599da9637f88da347858007f8e5c212
+dist/2025-08-05/rust-std-beta-x86_64-unknown-none.tar.gz=dacb8aa48387ad15380a094104bbcfabdcdd5f88e189d9203fd3e3f466b92fa3
+dist/2025-08-05/rust-std-beta-x86_64-unknown-none.tar.xz=ce2eb95efe252de2ecbe619b3805b01ec84863a9b30330dc4ad5683d67d7c9d8
+dist/2025-08-05/rust-std-beta-x86_64-unknown-redox.tar.gz=bf28f90b1b24eabd80da75262bd260ee811ef30a1ba94bdeb7a005f132ceeead
+dist/2025-08-05/rust-std-beta-x86_64-unknown-redox.tar.xz=99aa3603b7fdc84893a02e66a774e147439a1cfd77ba63818c58b11ae692058d
+dist/2025-08-05/rust-std-beta-x86_64-unknown-uefi.tar.gz=75c57e4a9367a6fbee02f8857da2dd4bce8bd20c8946a3c2460a77cb95af0972
+dist/2025-08-05/rust-std-beta-x86_64-unknown-uefi.tar.xz=552c14c20d1f786c8350882a32618951de0a06e0636fa3b8d69f2ffab7e7561d
+dist/2025-08-05/cargo-beta-aarch64-apple-darwin.tar.gz=4723292f91e645d3f86474ed55e52eae4f35af7458602d3da9d38b0a513cfeef
+dist/2025-08-05/cargo-beta-aarch64-apple-darwin.tar.xz=d0150ce874376c41950966b0385f011ebbbd5ef4955deec7829d8ccb669e9e86
+dist/2025-08-05/cargo-beta-aarch64-pc-windows-gnullvm.tar.gz=fb0a8a8dff4d42f9491ed9a0223a9541bbaf8691c831b5536220494c479b21e3
+dist/2025-08-05/cargo-beta-aarch64-pc-windows-gnullvm.tar.xz=6bd35ea43ab877d84bff4b32b965371b942b10c6f6feabb3a5b481a4c84513fc
+dist/2025-08-05/cargo-beta-aarch64-pc-windows-msvc.tar.gz=3437221155f338e81f55dea9d715b3958fe7d3a260d77d14725e62d0780bfc76
+dist/2025-08-05/cargo-beta-aarch64-pc-windows-msvc.tar.xz=94886636f7bf805809a8a1ac99b514036c5db1755ccfed61cb6cd01d57d244a3
+dist/2025-08-05/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=7f167793fc72f5fdb6bbed97e96684cfa089f9932d3a64239bc755fe7603e7a3
+dist/2025-08-05/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=1018ea99c4142db9fbf386547dee8396dc27d3d3608085a1b0b0e97e2d0172c7
+dist/2025-08-05/cargo-beta-aarch64-unknown-linux-musl.tar.gz=8e03af7a838e81c12c395ed76151aa6ead12b3e60effa3b0d775508118149058
+dist/2025-08-05/cargo-beta-aarch64-unknown-linux-musl.tar.xz=507de5fbe92e144dd37dc34123ee58b9e46805c85eccd4a759a117020578d742
+dist/2025-08-05/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=263ad4a9ed084dd76b6ea62d377fa470043f78e0343f7fb80d5c9b50659d8977
+dist/2025-08-05/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=ed850f484ee870172b721ab6824f0a15b41dd80ffc623557aa58a5b839d992c5
+dist/2025-08-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=afb4cdac4a3c28fe08fbba8b98962eec6c625f6a10a52ee8cc988881852b79dd
+dist/2025-08-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=7f332d11e74d76efe236a7858021a626d31fb856d9ad0745369b99d9fdfe3b44
+dist/2025-08-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=5c0c79bbf734c0ce18001cf27605f6728d83d24bc97ea5c78b423fb9faf46d96
+dist/2025-08-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=3aff39ef7b9e8adc2e6bca19c2940287c4e091ad7ce4503c46334e6969ce0c95
+dist/2025-08-05/cargo-beta-i686-pc-windows-gnu.tar.gz=af99a5778ab4c9cea122897bcd3ea1626893156fb71346d66a584553d6531469
+dist/2025-08-05/cargo-beta-i686-pc-windows-gnu.tar.xz=8425eda844728c0353b4c7edc4636141dad265e461addf009cfa1a224df0e7cd
+dist/2025-08-05/cargo-beta-i686-pc-windows-msvc.tar.gz=46d1b318b6cf826d8e7e694e54ce5b9c651dc2f8facf32ddebe21fc32e1e8dc4
+dist/2025-08-05/cargo-beta-i686-pc-windows-msvc.tar.xz=bef58a9f31aa3434152f79b2e271958fb07e925c938a569d1c9431f7764d19f1
+dist/2025-08-05/cargo-beta-i686-unknown-linux-gnu.tar.gz=c432ae4d909a21336a6645b85a90ec541818424bb76da16b19979a61a11845b2
+dist/2025-08-05/cargo-beta-i686-unknown-linux-gnu.tar.xz=053c02b341219d583caba881e525eae2cbb125ecc188e1b43d641fd7f3f027f2
+dist/2025-08-05/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=40542d76adaebdbc3fb16047a8324d439abba0485d227253614beddcc3cee2dd
+dist/2025-08-05/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=d25210467dabf91917eefad9a5a415a3912a31b37ce1fd3d755b6c72b3a6ce8a
+dist/2025-08-05/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=09755de73380c39daf64208df9708613ed6f8790e2f5cf79e80cb7826fd74f28
+dist/2025-08-05/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=e8eab1aa5b41c04b518d43a86849307cbfec76df13c834a460c546ab6b170089
+dist/2025-08-05/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=93398391d308bd0c08fa2a7bab7bb6a38b78400280cbe765604a3da9d6caeb47
+dist/2025-08-05/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=ed37a7c5a8c62db06e709779b81d1e013975feeb82c185c76bb3d218aa142cc4
+dist/2025-08-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=a398b3ff0967b1ec2fdc2716a6b2c3a04defc14ebed577d93e45040aa5552dc8
+dist/2025-08-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=51d6a1a3e71713157a4e6291023b8393e21334a952a947f82f9636a725989281
+dist/2025-08-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=cef935747fe5205c3c5944f4dcf80e3111d2859616e7d727b8a5c77abe2d9fef
+dist/2025-08-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=fcb8aee743adcc3796b564570e0ad6d9950031160ba9a6cafbd92af2f0a0c213
+dist/2025-08-05/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=73b2c9676122e842a73a8a9890f1e1aac426f75449a99b4fc0ae3f5dd5ce238e
+dist/2025-08-05/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=ba293bb860349ee4732c5363d38b5e386544a25f65ef8ee33850061bc84bfe64
+dist/2025-08-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=bff3ac251a42b1664a544706185826a4d9137cde990620dc73951252d2d7fb41
+dist/2025-08-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=61056d4405af01b4b1c3134af8e83ed86473d0846beb41d3ab72df92edf316a6
+dist/2025-08-05/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f89a30322a3621c4737f932788f4ca78c83b9f2845e324c4944522f35d44baf1
+dist/2025-08-05/cargo-beta-s390x-unknown-linux-gnu.tar.xz=394d522c9553182cf5f496e2b5324499c1845c0a0621fa527aaa925946b58d21
+dist/2025-08-05/cargo-beta-sparcv9-sun-solaris.tar.gz=0b18adbb22b34448576e6a3ba637c7565d369e1c994474337bed48b3cd0b0231
+dist/2025-08-05/cargo-beta-sparcv9-sun-solaris.tar.xz=c57709b87524d29661f77df3e3585bae4776fb3fb6de3874edb942f724543a89
+dist/2025-08-05/cargo-beta-x86_64-apple-darwin.tar.gz=c8faf66575d43fcbc03376225ac22d571def08ed1fc239d468c15929d9ecd393
+dist/2025-08-05/cargo-beta-x86_64-apple-darwin.tar.xz=538d81c3fe2b5a9edfc1e99655120d37fa159dcf761e1ddbe5233115e39b38b1
+dist/2025-08-05/cargo-beta-x86_64-pc-solaris.tar.gz=a2fb63b0a2cc3d3ea9523c8ffe61ba9ccb367dff136e6fc39aeea6400034363c
+dist/2025-08-05/cargo-beta-x86_64-pc-solaris.tar.xz=02e8990865ef8f14a31e4d0f17be4cc0cbecda7e82e062b4b9cfdb99dd45156d
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ba86f300cd40cb3cb23ac41970246ce54c03ee153f86127a379fecda930c020b
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-gnu.tar.xz=3bc0bf2da392ac52bcf2aa1dc19bea1a86bd7a4fe246feaae862a792c82ec476
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-gnullvm.tar.gz=68a2a34e656395fabd42d20b7008d96b2a86e9a47caa52e6e2613ccb3b1b2d8f
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-gnullvm.tar.xz=1e2e31fe2306e26bfe58c49a99cc89664e8a7857c2c18ad74c20cdb35bd3c586
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-msvc.tar.gz=5fa21f665aa40fab1896bd4a49dc5608b4b453d26f4b975771908634c699ab8e
+dist/2025-08-05/cargo-beta-x86_64-pc-windows-msvc.tar.xz=adc5900506d399246960445c1e2d59f0c4b2a5cfeff9972f1617de030ce82bfa
+dist/2025-08-05/cargo-beta-x86_64-unknown-freebsd.tar.gz=a2bbb1d5fa283e77ddbbc0c8d69e36b9c2bbb01912f302f522af48c2187327b3
+dist/2025-08-05/cargo-beta-x86_64-unknown-freebsd.tar.xz=11e1a51740a728f5825364a8679b28454a68e7efc96320730f9b58a8fc2e6fae
+dist/2025-08-05/cargo-beta-x86_64-unknown-illumos.tar.gz=9993f4130b5ce50898e530e7411efe6923a36b5d56459ab672b1395717fe69bb
+dist/2025-08-05/cargo-beta-x86_64-unknown-illumos.tar.xz=0a41315ced9f4fdce9c1877a4c27e5cca6e494f5dc8c2560334a5b75d42f495e
+dist/2025-08-05/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=6b8f74b1c850093acb7227306caaed4581d70d015ebb0bb5f924af1c8bee7bd1
+dist/2025-08-05/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=f6f7bb4e4f1156329946d83bad5893e508645dd76b9ce522a53ea673791da006
+dist/2025-08-05/cargo-beta-x86_64-unknown-linux-musl.tar.gz=68c829663d6166661563704e25a6e85a973705e12efc9265a23264b9ffbff4d7
+dist/2025-08-05/cargo-beta-x86_64-unknown-linux-musl.tar.xz=2c40e68c9978e58250f0e017b5cdb2fc390f26ef96324129c489f55898784488
+dist/2025-08-05/cargo-beta-x86_64-unknown-netbsd.tar.gz=65166585138bc6f09f54f88ee889aea6d4e63019d64a684798341d6b332ce99d
+dist/2025-08-05/cargo-beta-x86_64-unknown-netbsd.tar.xz=97491edef98b3a13b0571907555bf5867be13ec8fd4af69142db92a8deaf8586
+dist/2025-08-05/clippy-beta-aarch64-apple-darwin.tar.gz=b933611d47ccbcf5aad43f1134cc72ac708fdf59bace0dab75cfe139e2357373
+dist/2025-08-05/clippy-beta-aarch64-apple-darwin.tar.xz=c3d473e366db3b271cbe438b3a5531e9c5a72e28248d94de0f81ee93a8a2e7cd
+dist/2025-08-05/clippy-beta-aarch64-pc-windows-gnullvm.tar.gz=e5b4fc054121eb13b21171b2e851dc1c824e11aad1257dc92b4ca9e332898b40
+dist/2025-08-05/clippy-beta-aarch64-pc-windows-gnullvm.tar.xz=40bddcdd9186cfb9f8763e8e289087c15c2c8b8ab78f41ba7380cdb08fedb0da
+dist/2025-08-05/clippy-beta-aarch64-pc-windows-msvc.tar.gz=7e7c47305708ae073ed8d86e621a3c0be0e135b2480508814665f24121588a56
+dist/2025-08-05/clippy-beta-aarch64-pc-windows-msvc.tar.xz=c4a5bfe2d48a2301adb4f7524cccd64f4a3ccecf985f131972a13bd221346454
+dist/2025-08-05/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=dd26d49359f6010e94e04198067f83c83e81618546d1cf51606d157a02b4938f
+dist/2025-08-05/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=e7c9834067311a87f547450108718582991498a102dfcba0e1a99671205e9bc2
+dist/2025-08-05/clippy-beta-aarch64-unknown-linux-musl.tar.gz=b584c26e267b0f7e105f65c436c12cfd6d9b8f2b92f9662a4797fa5e95455e11
+dist/2025-08-05/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6b0eaadfea879cfc8c758fce002ffe77e34484e167c496ac0659dcc789dfc080
+dist/2025-08-05/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=eebd0632971888cb3bcc3b07a06f25a47af594ce5606e8e1e069fe85ec702e5c
+dist/2025-08-05/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=946d6791e4e15ffca6195bd7c9bd2d160b9c65468fddc800948f41adc8fec597
+dist/2025-08-05/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3862815aa14e8122b70b39c1137088e0c2a724900d2d13ac2b37a1a430b23a1f
+dist/2025-08-05/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=8278e11b7ea2bc035e6de21f826a775d66273a9031195d8b887752137424f2e0
+dist/2025-08-05/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=83a847698eeafcbd3288d59013157d3d2a11b90b521ebadf1b26dac90877d11f
+dist/2025-08-05/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=308de9cedc422c2051661df74024ab26c59b86368fbf50ce4dd7b2b2907ccc8f
+dist/2025-08-05/clippy-beta-i686-pc-windows-gnu.tar.gz=95fe71a1f8e68f0f3a5306dfa04e269c636ad036908e201c1b4ed7a3f99b1dc7
+dist/2025-08-05/clippy-beta-i686-pc-windows-gnu.tar.xz=5b8c928be909433fb005498a92d2fb3ff535f31c68a5e134523f9731cacb029a
+dist/2025-08-05/clippy-beta-i686-pc-windows-msvc.tar.gz=d736ec4f447f6b204f250b044b406b4e4b96f014887b6f7755b037e211aad3af
+dist/2025-08-05/clippy-beta-i686-pc-windows-msvc.tar.xz=8a4ac568284aabb994964323465c7287715d3dd4ab881271a4746d2ae5390ffc
+dist/2025-08-05/clippy-beta-i686-unknown-linux-gnu.tar.gz=d8b87338abdb4123eb25dd778d038c516c5bd472e1426b5a5f74f25126957039
+dist/2025-08-05/clippy-beta-i686-unknown-linux-gnu.tar.xz=ebb6dcc1b038deff6a966062ca3a966d3426f8932e5aeba398636a2d2e9be0c0
+dist/2025-08-05/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=51bf4e84be5b677ad9afba442d9567b96f59209219cddad5eb3f49b788bd8fe2
+dist/2025-08-05/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e63e3346089c7f300bdc73521def20cd2a012f8de98b8b05a653e85f3516371c
+dist/2025-08-05/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=aeb3782ca34a0ac47420109c241041ebbc029050a690a5c828c865108f56ca18
+dist/2025-08-05/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=80dabbd511bd5bdfc944d7613a02c9bdac702abf2de916222a37e59a92c2e577
+dist/2025-08-05/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=9307396973615663330474ec145efebd4246c6bae5d979a80b6d93f832af0137
+dist/2025-08-05/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=fb2a34f9472d2c1beb1381e9ff8bca23d9058c978fdb2e52a3c7f0cba8305c59
+dist/2025-08-05/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=e985eebd182d78604861ce60aba5078e98a9a078b76752da8fabcfc5fa471fc3
+dist/2025-08-05/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=1092ddf60ba04418f91c1e51f9c9da1e0d6b61dbdb104fc8028043dc1a33caec
+dist/2025-08-05/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=bf0238a4909fa15034f067d5a51e38e43c91e69f29f51c39246d5c0b23925042
+dist/2025-08-05/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=39caa6aedcd746ed1c4745e207cf8cd65de7b774f15e8892987ce2c3fdde543e
+dist/2025-08-05/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=b19ef1a8cdc21925887ced0c594ff5ab658bf66a0d137c01b6375fcdd0de8e35
+dist/2025-08-05/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=0ec300c1e791f946503db692e602680acf11857715b9ecc87cb446ac10d2527c
+dist/2025-08-05/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=e7c8fe214ffd70599648cfacb50b3457597b479d320bf8383869dda8b0559d42
+dist/2025-08-05/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=d8ba0c42074c2a94dff3b05f2388f17225044485abd0459e155928f4762c8988
+dist/2025-08-05/clippy-beta-s390x-unknown-linux-gnu.tar.gz=510b9c9ca885a8e91c3d25f14cbfb34a7a927d374fa1a9149678d7ed9c4e4c2c
+dist/2025-08-05/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b53697799d99beb46fc17b3cca8ccfdc4ecbf7f3e1fd47f031852f07fb749ea0
+dist/2025-08-05/clippy-beta-sparcv9-sun-solaris.tar.gz=f3109a1dd87c23256057fcc94d3fade0b49d20a51040b4fbdda366f5b7c9b58e
+dist/2025-08-05/clippy-beta-sparcv9-sun-solaris.tar.xz=ba265d781254d0b032d836a440c94c31ca33bc136e027ad05332cfc0cf40bf54
+dist/2025-08-05/clippy-beta-x86_64-apple-darwin.tar.gz=74c49a7cd4b6605b9a43961415fcaed1197b8f5aca798efd4b62a15d837b956b
+dist/2025-08-05/clippy-beta-x86_64-apple-darwin.tar.xz=69128daabb11fd29720752bb13d83ef4bb3faa1d4aea8d525da2cb04f42b6010
+dist/2025-08-05/clippy-beta-x86_64-pc-solaris.tar.gz=e1975507778e448ac9b3040f330340f3a7d54e6dd40357494e3d891008375364
+dist/2025-08-05/clippy-beta-x86_64-pc-solaris.tar.xz=43c142c870116f4c2408f4b3208680b81390a4b37805f5a32696ad17bb313b48
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-gnu.tar.gz=ccd8806b6614edb270a2816cf0dc3b6376046fe58d258d296ffb222929d42d91
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-gnu.tar.xz=21148cd754493da3cdf72adc8da19ebfca1da8d642e1bef51782772241b48084
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-gnullvm.tar.gz=5a7cecb6c054a71ec5b1fb284f6bf2c069925fffcc1757ac631e8a2d08b116b0
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-gnullvm.tar.xz=b451057a4a75341924072fe26334eefce8b6eaa3edd79d3226eb02c1c99fcdb3
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-msvc.tar.gz=74e9cea693203c6217934549694a240460dda2818b144bac5777f41c44a06d53
+dist/2025-08-05/clippy-beta-x86_64-pc-windows-msvc.tar.xz=bd90fc3fc80f28ce415dc1cfd105d17ec5ecfc63fae017baeec734bf94f5d71b
+dist/2025-08-05/clippy-beta-x86_64-unknown-freebsd.tar.gz=fb61d60d6c66a4632911944b5c7858b8c055ab8ae5a194d78e7d7ba18b65e940
+dist/2025-08-05/clippy-beta-x86_64-unknown-freebsd.tar.xz=bbc7b2aa6f05ecf391a757ffc5b6fa6e0989d00f7e8fa48b83faca8996f99dd1
+dist/2025-08-05/clippy-beta-x86_64-unknown-illumos.tar.gz=10e8be6eb15269cb2d0573e19e3a5004dbbd2b14e2f016d6b9c60713e22f716b
+dist/2025-08-05/clippy-beta-x86_64-unknown-illumos.tar.xz=c3748db93829d3f5d9c5498592d247468125ca301ef238c41e42d37b7b90c6a4
+dist/2025-08-05/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=5a0365eda14ac1a366f3c480a2358eccbfcbfce86323711d7fcfdcfd85652b42
+dist/2025-08-05/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=908576635e79fe589583f18bd6ace4c488cd11ed0c59501082bb0b397df24f39
+dist/2025-08-05/clippy-beta-x86_64-unknown-linux-musl.tar.gz=79fd42cffac98024308c511144b716d18693b902dbdc1c4b88645bc7d4ae7109
+dist/2025-08-05/clippy-beta-x86_64-unknown-linux-musl.tar.xz=a3a616554ed25630df9f8cef37a5d36573e6f722b1f6b4220ff4885e2d3a60de
+dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.gz=ad1849cb72ccfd52ba17a34d90f65226726e5044f7ffbe975c74f23643d87d98
+dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.xz=608001728598164e234f176d0c6cfe7317dde27fb4cbb8ad1c2452289e83bf30
+dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.gz=b33b3bd26dd4518802b325e7c151ea73fa6844bc710ac2d2c8fb55a27c5d7e2a
+dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.xz=c900e816a94a0ddd7701c64051ba0e0244c5799e77189e26df109649b10f636f
+dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=aa7c344a52c69ee9b9e68007da806f5741688ce3917c377b6563043703e7d867
+dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=d76d7c6ca6cd5286bee12cabec166a3d8848b28a484a105b56bd5687674bc4c6
+dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=ea4d7c94a12485958b15e7a2782f9b8a09e065c021acd2894e7a905cadfa7489
+dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=4a85be8477cf4b23971fedf3b06b404cf2231f8fe941630e3e73dc902454b96e
+dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=385625349ab2e79887e2630fc861dcdd039190af36748df27500f7ea45a515f9
+dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=50cec6b681ae63ebcd60ce6cb6d328f49939c3cac1aa6b71ce76a5a3902cb52c
+dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=09a141bf2e457e91abf688c8084654e5e0b932418e351da2c0daf6cf89b77e56
+dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=7aa6d3bd020e903c842725bb3ec9dba1881f2e9cd748953c23c658ef93d49dce
+dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=c00a4b1ad60af59609e3bc61f042f9c4152de26687dcd120da173d61264b88ab
+dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=fcca5576b2f0bdab5bf7dd7ecb6ea956285aa3c129a1ea9facaf517f09f20c2d
+dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=434d9bff2e5693db416701730af1a71767715e98d674cf7273b32f76128ccab1
+dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=af48289fe813a45eb78373d80f01f060ebd2ce6337763d1ee8ea6f5080cb4eb1
+dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=68b2704b80c8f0706dc4bdba4db3b620afecbe086a7d858749d84d56f130979b
+dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=930b287659104dbf4fe759d450a4126b7a0f855fbe8fd7d3ab11aadb18ceccfa
+dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=7580ce2af926de7e07ad2313ae6397a624b10532556f7f9b9cee8ecd5addc697
+dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ed19716bdb95eb04e64299c04725c7a0b92c66121856ab891bb67a797c8b1087
+dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1d4077c7b42aabe2b80a19f3c96b457901f81667d62a5be9df617543245f0d8c
+dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e0203ce7cea0c2125d8d39d92c5137b2397115c4d99f42d0b23746d0270c78d2
+dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=0a836d9d2fc5824aeb4afd5eba709c0e3c6d4403ca8815356a0ac8735cbc95dc
+dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=f656cb9adff0aa53f47f15a937556e9b1a9418f33dff39350e48ab8c02da987a
+dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=c44a884292ffeba027d3d029d6d53ccaa2bb85787e825c9cc1dca464046a7855
+dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6992586e7dc3b95ddaa630cb61f58ec88b5d7c488aed8476be25a92d0fb4a3dd
+dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=6e053aee8964a26385292dc2e9b671995045bb736447059e536b1e7f09c79685
+dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=611d609f23f75a2b7fe304737abaf017fcf4594d9d11cbe014e91a90ee5ab27f
+dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=932f888a1a604358ad40d62bc0ca9a484f47715e8a5306fe77ae610ada4671ce
+dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=4eae3ed539b4ff8b39dae4ea4089081fa49807d31640129eec29b47030e8101e
+dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=13c65d2427c063961c19b20aa4f25bb11b3189084e2f0a798a846b95c630735b
+dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=2f8e8ec9a4c0187174a0d8d3c2addf75e68a2d60920ae100f37efb5e57a45033
+dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=e11b21d9aa403a1202c299390210d11d403501f6f55cc7ec24d6118461545825
+dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=ece7d348df665d6ff6d061e911c6bb4c9d4f161e63e888d3a66f17b533843886
+dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=d87c2370e2346587d71994ba31a0455932760507fcce680ab39322619179c429
+dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=030355ceaa2697d8b2d2de41b56cc4ef50124aa81b2f226cf0d56a1e011e0fa6
+dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=d725272b6b92059afd637a3edfc6dc2b22013bf4e70a0ed1f7c5aad3c6a71fca
+dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0c3e7de4e92f696585bd6a85c30fab337548e4393c3ec5b52832f3533acb063
+dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=79f6a3429c2ee29e1350bfce20f7f5ca1e5ec46720194cf3f34977fe446c79cd
+dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=777568cc6df1ce1b96f291027a5024109c189e83e2e2c046a3248e3a1cbedcc6
+dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=2528c1e6256bd9e73174b435802702bbe66eaaa4cff3748d3e5b7580ca7bc789
+dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=2f62d01498b57395e03ddfffc4e0b5cdf78a7fb6f5308440b8eee24637874752
+dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a9b2f612748bc7a88eced4462999c67eeba0ea46f4a73977513c34c09286b0a3
+dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.xz=a8137526bc41ab13a624aa5c9895abcc250f38776aeb690a7939baab1093f388
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.gz=18015624ba6cc1892d944d6f3c82e0b22fc5ff85ac074d25ad80fb4af12f0172
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.xz=bc0f5d324b4b807b0a378aa0e132a429c57c4773c6d9d30e9215ba835de1a0a5
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=de159bd0f81d54906d8020b3da80ab3319292907c3f0c9c68654f8e6ed900135
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=6dd48c3a64fcc0f2f99e4cc643cf82f1a7efab1921918fd37953c64125982606
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=8ba8c7ce8715fb378758ae8bd6c1538e538c2dfe86771db43b7903f18a384ad3
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=4259f65663aea76e1397c677bc286588cd4b6f8694647c738efc55e5616bc084
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=bfd3e1434e5b816d9d338e6c56203f58b5c1a89499ca03099d4d86b3c665f0d1
+dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6260a7487d7d3759aea9e6691ac77ee38948a538f8b973459f444f98912753e0
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=c10b36a6ac99d8e1de73c3ae0ca74ef10600baf7a3963f6885282b97f703f992
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=b8de069c788f4a6c195d7a429ed656a45ea2a9a5775138de46d79c1c3591e70e
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b0f0d9331d213015493e080f8cd06e6ed955693981241acd692a92dd545df66f
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=91ed6b2792622c68a5cc3698650860373305a39162b2b643b1c219cab6debbba
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=b1920a45d2532f41956b2c1112cf8c590243b1417bc48f3922056e1d62a27a1d
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=1825ed54530deb070d6f894cc12ca157be57a37e6d7ccc6007a51674eae42082
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=ac01818b1cc9130b4dcdad9db8137382655d21df9d6e7edc5cd0f84c71bbe787
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=21ee5aeb048e5337b3231b4f3ca8a6bfacc3a1cc23800052093d360ca22b3b78
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=020995d3e24b4e72b0166662fd2e6969f397baa728999bbd09bce76e5381e0b5
+dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=4a09cad2bd24ae6a15c83fb9098f66208219d3ab14c9fd46a3ce7a3c8efe6119
+dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.gz=25e5461350634cbd4b38dce96bc6ba6a9fbdb87caed51f26dfa058105bbccb4a
+dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.xz=e8774ab1e12ba4d3d088dfb0c6a929b3fb6866db035eb10a60b203a6af59f490
+dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=0094366fa4b8f33c7ec5bb75fa5116044c76f3b7bf4a96b5a48b31dbf6f080eb
+dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=6686cbf9182560d9b691ac56b3e89ed76c4fe6340dd036820a1a126e2ff41689
+dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=d3e23b1b5ac10b0cc406eb5397da7fff30aa4e558832379debf4410551ebdc4d
+dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=fd2771191a84469c6b1fcef7e90388f4699ef087e082c9838ca2bb2d1d50b399
+dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d4848e6a71e9cb6b87e46843f61da911ae81266f5c3aca10f85120d069d304bb
+dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=b1e9c97f2b1c06ebf1dc00cf5fa23191a86e3ef234ebaeeced2bd41b3e59b656
+dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=4d68bc5ecf31127f67d1bb2359e9ca475ea7a0c396da29b00781929f1f00ba6c
+dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=8588747d7ce6c5a9b68ba6805b63449695e60d2e9ea7f3f0ad5f4e5a04d9062c
+dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=4ebb3bd5e06737d2b61f249a674cda32a2a58e871039c37d49c2d6c8d2ecd6d9
+dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=5740de96cfbdcc5261e0df10e9c7ec63e28bd553f9691a8e26e6fe9f76cbbee3
+dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f4a9b5c0b6d2cf2f86feac062018e044cfbd05c9cc8243e2ff44d8196745
+dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=a1f54aab1b4a5ebc09d9b57c892072dfd8d5280fe7a0f3dd3f643ffc72992d34
+dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=cac4ed0ff044997a35471f6c291bb165b48cdcf3f0a0a4df24d7c91cbe121362
+dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=47e6083275169ef75dde6daae2bb9ca599ea03ce56d31945e9e0b42d09ebf364
+dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.gz=95c87a447d33748fbfa1e9136dfb290814a7dfb1a28efc45f14f0c7830ec49bb
+dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.xz=52929264f954609165aca5d925d6a1f0e41f78647b45edcd8a7c8c3f872c4bd7
+dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.gz=f8db463c7c5aeb7fda6d0aa2e4d460d42a7fca5ec8b9b4d8a97e4f988c72a1bd
+dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.xz=b33e23dfc673dda3eaa81d3c2d690e68cbc95bfb09864c8b2307029b0509c4f0
+dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.gz=f4f243206778a3997e3ab63170182a6e210cedd47c2a17358146e3e2cb892912
+dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.xz=194cda3450befacd2da23bccf836995f09a85e7e9c6d4ba5613cbb3c1768815f
+dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f189ae4ab931c61eef04b5748b696070b998699315629a3b95d4f0b4cdae9ff9
+dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=23c82bf0d9f5532d94a24cfaeec66fc5f02e1b28c854e5689babd41ebcfc0ad2
+dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=3e76a7201dd24f9d79589445509f0c80e6902864731f71d1da3f5343a75aa5bc
+dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=3a62df3e5497fee4e56bc428db422990c7df924f72dacb6897b3783560a967c8
+dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=cc5c126bb1ad662dc78a3b4b039e6cd32445b45b163886180fda199cbfdae9df
+dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=1c9ecfef304fb901ec6f2cfd4e170d1f02511bb2a84de664718c20c7d154e313
+dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=76b6c1025d9dc045bfdfb5e0ca8e9cde674d0c40bb67f600ecb0e765b9f71f03
+dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=bf08f2bbd2197919acfcdf8db8130882ec8f77cb41371729072e7e94cc54997b
+dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7e5e5816a18c3b22a5a5cd0814206c3cb53c7fa2ce3d36c9c045e1fac87b0747
+dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6470b0bbe1a82064de13bd9540acbd2368421e8b000cfd8af05886a48cf11d2c
+dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=1a2cfbf02e55995793bdd9cf3809ace31a3d9900667ec6d5e71c6c63af26f578
+dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=7ea6594b669fa77481ff8ec4e8cf447c11e021a412584e1e60f0baed0976316e
+dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5cbd5821ad528d90f191a17d019b71ac2beea413b00ceec78aef9433832b2469
+dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=86002592eb275d582ec8656d903ddd2247a0fcfdb2c6d90f337735a574debb9a
+dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1c420af2bb6af11b2a718ff02d96794e9916a7f538d622b418f39ecd451e1fd6
+dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=1c33f80fbc3284d8499ec03bddb5bd9ebbe7e0da1aac6675d8442a3443440c3c
+dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.gz=366a9097aaf91fd8b2853b2f94d82b8baf162dae5ef1b514072b4da19fec87a5
+dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.xz=eca0aaa16e5e7006b19e56330157545d0fb56a5e590c92e041afbc8205c35ab0
+dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.gz=f2665645f498cc57e0b6cb052715afd264b7bb3184be58d50f528562a1610111
+dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.xz=2d5dba8ed862c80035ef742d9a45c1e122228219b4e1da8fd8b920eb589bbe71
+dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.gz=6970602ef52246883c2df83795cca94356a1e978265facab3dd3f838707d31d3
+dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.xz=92e7a314326015586054cdd5044c3123f41972432b2167f0dd551ee9380d66ca
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=5405ac07a580ba16b0f95ed0fc56a24318e8aab7abfe04c2ed3c87f9d6f1edcb
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=10d189c68491e15b6dd34b7f47bf8c72ccb8ab7260c4d815cb51046fd24ad76c
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=812a29f858412b9c256184e8e2b3d65d0c9912d7f4157a9ba640c8231caa5160
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=aa22d4547d85669a17c8a475baf533614d8d0547b1e386dc11bde66f215a874c
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=5e60c66f60a4358c0f8b2fea5577f71f4c056c7b2d0afefd9289f782004fbc63
+dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=6d975c907e1def685c14fe6e460001af0362824f771585f9b1ccc2cc1ea71fac
+dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.gz=465206e95e2c6a7731ca55db9e576f1f78e9d356ba81c6687752793101c80b92
+dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.xz=13cd73704262a891ea825201e6583c171f7a920c1be5372b4cccf5cbe3d294fc
+dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.gz=a7bf182bf19812d41e103a8d89e6c3457c1c9d0ddd800f59fdc3d94df587e3c3
+dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.xz=43da78e7dca1415ecd756ef13fd08a8358b8deedf406d18801f36e38843a704f
+dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ef6381475d22aff666429754e25855e97a4dc39e8d508c02a0e353df58afcaba
+dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=238910ad25562d4f7fa6c83d92f9cad5ec3817191907958fa646251c9bcdb690
+dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=df2464c2f2c9233f2009ac73924e95b7dd395c8575874a3391fe2f3dfcfda327
+dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=99c5a9d7f0e7f9e3acde96bfd1d23a11100be81a3651e8267e6e0ffca6bc553d
+dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.gz=705dd37d72d99694234af13a561dd9995a0e4c2bfd888aa451b666f49a7083a7
+dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0dc9551d63131336cd97b7bfca984970fc8e5c366b39e04a179673f7859f4c1e
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.yml b/src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.yml
index 464740640e0..a8202f6378f 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.yml
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.yml
@@ -48,3 +48,24 @@ body:
         ```
     validations:
       required: true
+  - type: textarea
+    id: comparison
+    attributes:
+      label: Comparison with existing lints
+      description: |
+        What makes this lint different from any existing lints that are similar, and how are those differences useful?
+
+        You can [use this playground template to see what existing lints are triggered by the bad code][playground]
+        (make sure to use "Tools > Clippy" and not "Build").
+        You can also look through the list of [rustc's allowed-by-default lints][allowed-by-default],
+        as those won't show up in the playground above.
+
+        [allowed-by-default]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
+
+        [playground]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&code=%23%21%5Bwarn%28clippy%3A%3Apedantic%29%5D%0A%23%21%5Bwarn%28clippy%3A%3Anursery%29%5D%0A%23%21%5Bwarn%28clippy%3A%3Arestriction%29%5D%0A%23%21%5Bwarn%28clippy%3A%3Aall%29%5D%0A%23%21%5Ballow%28clippy%3A%3Ablanket_clippy_restriction_lints%2C+reason+%3D+%22testing+to+see+if+any+restriction+lints+match+given+code%22%29%5D%0A%0A%2F%2F%21+Template+that+can+be+used+to+see+what+clippy+lints+a+given+piece+of+code+would+trigger
+      placeholder: Unlike `clippy::...`, the proposed lint would...
+  - type: textarea
+    id: context
+    attributes:
+      label: Additional Context
+      description: Any additional context that you believe may be relevant.
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 5a81b411291..2874aaf2110 100755
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -47,9 +47,9 @@ unset CARGO_MANIFEST_DIR
 
 # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
 # FIXME: How to match the clippy invocation in compile-test.rs?
-./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/string_to_string.rs 2>string_to_string.stderr && exit 1
-sed -e "/= help: for/d" string_to_string.stderr > normalized.stderr
-diff -u normalized.stderr tests/ui/string_to_string.stderr
+./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/char_lit_as_u8.rs 2>char_lit_as_u8.stderr && exit 1
+sed -e "/= help: for/d" char_lit_as_u8.stderr > normalized.stderr
+diff -u normalized.stderr tests/ui/char_lit_as_u8.stderr
 
 # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
 SYSROOT=$(rustc --print sysroot)
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index a92fbdc767b..bc60b1c57f7 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,7 +6,105 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[03a5b6b9...master](https://github.com/rust-lang/rust-clippy/compare/03a5b6b9...master)
+[4ef75291...master](https://github.com/rust-lang/rust-clippy/compare/4ef75291...master)
+
+## Rust 1.89
+
+Current stable, released 2025-08-07
+
+[View all 137 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2025-05-01T16%3A52%3A57Z..2025-06-13T08%3A33%3A27Z+base%3Amaster)
+
+### New Lints
+
+* Added [`coerce_container_to_any`] to `nursery` [#14812](https://github.com/rust-lang/rust-clippy/pull/14812)
+* Added [`ip_constant`] to `pedantic` [#14878](https://github.com/rust-lang/rust-clippy/pull/14878)
+* Added [`infallible_try_from`] to `suspicious` [#14813](https://github.com/rust-lang/rust-clippy/pull/14813)
+* Added [`doc_suspicious_footnotes`] to `suspicious` [#14708](https://github.com/rust-lang/rust-clippy/pull/14708)
+* Added [`pointer_format`] to `restriction` [#14792](https://github.com/rust-lang/rust-clippy/pull/14792)
+* Added [`useless_concat`] to `complexity` [#13829](https://github.com/rust-lang/rust-clippy/pull/13829)
+* Added [`cloned_ref_to_slice_refs`] to `perf` [#14284](https://github.com/rust-lang/rust-clippy/pull/14284)
+* Added [`confusing_method_to_numeric_cast`] to `suspicious` [#13979](https://github.com/rust-lang/rust-clippy/pull/13979)
+
+### Moves and Deprecations
+
+* Removed superseded lints: `transmute_float_to_int`, `transmute_int_to_char`,
+  `transmute_int_to_float`, `transmute_num_to_bytes` (now in rustc)
+  [#14703](https://github.com/rust-lang/rust-clippy/pull/14703)
+
+### Enhancements
+
+* [`module_name_repetitions`] added `allow_exact_repetitions` configuration option
+  [#14261](https://github.com/rust-lang/rust-clippy/pull/14261)
+* [`missing_docs_in_private_items`] added `allow_unused` config for underscored fields
+  [#14453](https://github.com/rust-lang/rust-clippy/pull/14453)
+* [`unnecessary_unwrap`] fixed being emitted twice in closure
+  [#14763](https://github.com/rust-lang/rust-clippy/pull/14763)
+* [`needless_return`] lint span no longer wraps to previous line
+  [#14790](https://github.com/rust-lang/rust-clippy/pull/14790)
+* [`trivial-copy-size-limit`] now defaults to `target_pointer_width`
+  [#13319](https://github.com/rust-lang/rust-clippy/pull/13319)
+* [`integer_division`] fixed false negative for NonZero denominators
+  [#14664](https://github.com/rust-lang/rust-clippy/pull/14664)
+* [`arbitrary_source_item_ordering`] no longer lints inside items with `#[repr]` attribute
+  [#14610](https://github.com/rust-lang/rust-clippy/pull/14610)
+* [`excessive_precision`] no longer triggers on exponent with leading zeros
+  [#14824](https://github.com/rust-lang/rust-clippy/pull/14824)
+* [`to_digit_is_some`] no longer lints in const contexts when MSRV is below 1.87
+  [#14771](https://github.com/rust-lang/rust-clippy/pull/14771)
+
+### False Positive Fixes
+
+* [`std_instead_of_core`] fixed FP when part of the `use` cannot be replaced
+  [#15016](https://github.com/rust-lang/rust-clippy/pull/15016)
+* [`unused_unit`] fixed FP for `Fn` bounds
+  [#14962](https://github.com/rust-lang/rust-clippy/pull/14962)
+* [`unnecessary_debug_formatting`] fixed FP inside `Debug` impl
+  [#14955](https://github.com/rust-lang/rust-clippy/pull/14955)
+* [`assign_op_pattern`] fixed FP on unstable const trait
+  [#14886](https://github.com/rust-lang/rust-clippy/pull/14886)
+* [`useless_conversion`] fixed FP when using `.into_iter().any()`
+  [#14800](https://github.com/rust-lang/rust-clippy/pull/14800)
+* [`collapsible_if`] fixed FP on block stmt before expr
+  [#14730](https://github.com/rust-lang/rust-clippy/pull/14730)
+* [`manual_unwrap_or_default`] fixed FP on ref binding
+  [#14731](https://github.com/rust-lang/rust-clippy/pull/14731)
+* [`unused_async`] fixed FP on default impl
+  [#14720](https://github.com/rust-lang/rust-clippy/pull/14720)
+* [`manual_slice_fill`] fixed FP on `IndexMut` overload
+  [#14719](https://github.com/rust-lang/rust-clippy/pull/14719)
+* [`unnecessary_to_owned`] fixed FP when map key is a reference
+  [#14834](https://github.com/rust-lang/rust-clippy/pull/14834)
+
+### ICE Fixes
+
+* [`mutable_key_type`] fixed ICE when infinitely associated generic types are used
+  [#14965](https://github.com/rust-lang/rust-clippy/pull/14965)
+* [`zero_sized_map_values`] fixed ICE while computing type layout
+  [#14837](https://github.com/rust-lang/rust-clippy/pull/14837)
+* [`useless_asref`] fixed ICE on trait method
+  [#14830](https://github.com/rust-lang/rust-clippy/pull/14830)
+* [`manual_slice_size_calculation`] fixed ICE in suggestion and triggers in `const` context
+  [#14804](https://github.com/rust-lang/rust-clippy/pull/14804)
+* [`missing_const_for_fn`]: fix ICE with some compilation options
+  [#14776](https://github.com/rust-lang/rust-clippy/pull/14776)
+
+### Documentation Improvements
+
+* [`manual_contains`] improved documentation wording
+  [#14917](https://github.com/rust-lang/rust-clippy/pull/14917)
+
+### Performance improvements
+
+* [`strlen_on_c_strings`] optimized by 99.75% (31M → 76k instructions)
+  [#15043](https://github.com/rust-lang/rust-clippy/pull/15043)
+* Reduced documentation lints execution time by 85% (7.5% → 1% of total runtime)
+  [#14870](https://github.com/rust-lang/rust-clippy/pull/14870)
+* [`unit_return_expecting_ord`] optimized to reduce binder instantiation from 95k to 10k calls
+  [#14905](https://github.com/rust-lang/rust-clippy/pull/14905)
+* [`doc_markdown`] optimized by 50%
+  [#14693](https://github.com/rust-lang/rust-clippy/pull/14693)
+* Refactor and speed up `cargo dev fmt`
+  [#14638](https://github.com/rust-lang/rust-clippy/pull/14638)
 
 ## Rust 1.88
 
@@ -6260,6 +6358,7 @@ Released 2018-09-13
 [`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block
 [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
 [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
+[`possible_missing_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_else
 [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
 [`precedence_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence_bits
 [`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl
diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md
index 72ab08792d3..42ed624ec21 100644
--- a/src/tools/clippy/CONTRIBUTING.md
+++ b/src/tools/clippy/CONTRIBUTING.md
@@ -199,26 +199,34 @@ currently. Between writing new lints, fixing issues, reviewing pull requests and
 responding to issues there may not always be enough time to stay on top of it
 all.
 
-Our highest priority is fixing [ICEs][I-ICE] and [bugs][C-bug], for example
-an ICE in a popular crate that many other crates depend on. We don't
-want Clippy to crash on your code and we want it to be as reliable as the
-suggestions from Rust compiler errors.
-
-We have prioritization labels and a sync-blocker label, which are described below.
-- [P-low][p-low]: Requires attention (fix/response/evaluation) by a team member but isn't urgent.
-- [P-medium][p-medium]: Should be addressed by a team member until the next sync.
-- [P-high][p-high]: Should be immediately addressed and will require an out-of-cycle sync or a backport.
-- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync.
-Or rather: before the sync this should be addressed,
-e.g. by removing a lint again, so it doesn't hit beta/stable.
+To find things to fix, go to the [tracking issue][tracking_issue], find an issue that you like, 
+and claim it with `@rustbot claim`.
+
+As a general metric and always taking into account your skill and knowledge level, you can use this guide:
+
+- 🟥 [ICEs][search_ice], these are compiler errors that causes Clippy to panic and crash. Usually involves high-level
+debugging, sometimes interacting directly with the upstream compiler. Difficult to fix but a great challenge that
+improves a lot developer workflows!
+
+- 🟧 [Suggestion causes bug][sugg_causes_bug], Clippy suggested code that changed logic in some silent way.
+Unacceptable, as this may have disastrous consequences. Easier to fix than ICEs
+
+- 🟨 [Suggestion causes error][sugg_causes_error], Clippy suggested code snippet that caused a compiler error
+when applied. We need to make sure that Clippy doesn't suggest using a variable twice at the same time or similar
+easy-to-happen occurrences.
+
+- 🟩 [False positives][false_positive], a lint should not have fired, the easiest of them all, as this is "just"
+identifying the root of a false positive and making an exception for those cases.
+
+Note that false negatives do not have priority unless the case is very clear, as they are a feature-request in a
+trench coat.
 
 [triage]: https://forge.rust-lang.org/release/triage-procedure.html
-[I-ICE]: https://github.com/rust-lang/rust-clippy/labels/I-ICE
-[C-bug]: https://github.com/rust-lang/rust-clippy/labels/C-bug
-[p-low]: https://github.com/rust-lang/rust-clippy/labels/P-low
-[p-medium]: https://github.com/rust-lang/rust-clippy/labels/P-medium
-[p-high]: https://github.com/rust-lang/rust-clippy/labels/P-high
-[l-sync-blocker]: https://github.com/rust-lang/rust-clippy/labels/L-sync-blocker
+[search_ice]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc+state%3Aopen+label%3A%22I-ICE%22
+[sugg_causes_bug]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-suggestion-causes-bug
+[sugg_causes_error]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-suggestion-causes-error%20
+[false_positive]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-false-positive
+[tracking_issue]: https://github.com/rust-lang/rust-clippy/issues/15086
 
 ## Contributions
 
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index f25f9ab54dd..daf1c98cdc9 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.90"
+version = "0.1.91"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 992ed2c6aaa..7f16f3a9810 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -555,7 +555,7 @@ default configuration of Clippy. By default, any configuration will replace the
 * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
 * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
 
 ---
 **Affected lints:**
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index 858366c8a5c..6ad2cf0d0b1 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.90"
+version = "0.1.91"
 edition = "2024"
 publish = false
 
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 555f54bcfb8..8167d75583e 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -44,7 +44,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "WebP", "OpenExr", "YCbCr", "sRGB",
     "TensorFlow",
     "TrueType",
-    "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD",
+    "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS",
     "TeX", "LaTeX", "BibTeX", "BibLaTeX",
     "MinGW",
     "CamelCase",
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index c03cc99b581..b9e6de79cc0 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.90"
+version = "0.1.91"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index ab47e309752..a3710ca5165 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -2,8 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
-use rustc_hir::RustcVersion;
-use rustc_hir::{HirId, Lit};
+use rustc_hir::{HirId, Lit, RustcVersion};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, symbol};
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index c2406bcfb64..c956738edf0 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -2,6 +2,7 @@ use super::DUPLICATED_ATTRIBUTES;
 use clippy_utils::diagnostics::span_lint_and_then;
 use itertools::Itertools;
 use rustc_ast::{Attribute, MetaItem};
+use rustc_ast_pretty::pprust::path_to_string;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_lint::EarlyContext;
 use rustc_span::{Span, Symbol, sym};
@@ -35,31 +36,38 @@ fn check_duplicated_attr(
     if attr.span.from_expansion() {
         return;
     }
-    let Some(ident) = attr.ident() else { return };
-    let name = ident.name;
-    if name == sym::doc || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason {
-        // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
-        // conditions are the same.
-        // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
-        return;
-    }
-    if let Some(direct_parent) = parent.last()
-        && *direct_parent == sym::cfg_trace
-        && [sym::all, sym::not, sym::any].contains(&name)
-    {
-        // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
-        // level `cfg`, we leave.
-        return;
+    let attr_path = if let Some(ident) = attr.ident() {
+        ident.name
+    } else {
+        Symbol::intern(&path_to_string(&attr.path))
+    };
+    if let Some(ident) = attr.ident() {
+        let name = ident.name;
+        if name == sym::doc || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason
+        {
+            // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
+            // conditions are the same.
+            // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
+            return;
+        }
+        if let Some(direct_parent) = parent.last()
+            && *direct_parent == sym::cfg_trace
+            && [sym::all, sym::not, sym::any].contains(&name)
+        {
+            // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
+            // level `cfg`, we leave.
+            return;
+        }
     }
     if let Some(value) = attr.value_str() {
         emit_if_duplicated(
             cx,
             attr,
             attr_paths,
-            format!("{}:{name}={value}", parent.iter().join(":")),
+            format!("{}:{attr_path}={value}", parent.iter().join(":")),
         );
     } else if let Some(sub_attrs) = attr.meta_item_list() {
-        parent.push(name);
+        parent.push(attr_path);
         for sub_attr in sub_attrs {
             if let Some(meta) = sub_attr.meta_item() {
                 check_duplicated_attr(cx, meta, attr_paths, parent);
@@ -67,7 +75,7 @@ fn check_duplicated_attr(
         }
         parent.pop();
     } else {
-        emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}", parent.iter().join(":")));
+        emit_if_duplicated(cx, attr, attr_paths, format!("{}:{attr_path}", parent.iter().join(":")));
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
index 409bb698665..fb86ae8da9d 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
@@ -1,8 +1,7 @@
 use super::INLINE_ALWAYS;
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::attrs::{AttributeKind, InlineAttr};
-use rustc_hir::find_attr;
-use rustc_hir::Attribute;
+use rustc_hir::{Attribute, find_attr};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
index 4ece3ed44fd..8a530e8cff2 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
@@ -1,6 +1,5 @@
 use rustc_hir::attrs::{AttributeKind, ReprAttr};
-use rustc_hir::find_attr;
-use rustc_hir::Attribute;
+use rustc_hir::{Attribute, find_attr};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
index 011962846cb..10fe1a4174f 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
@@ -100,8 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
                             cond.span,
                             BRACED_EXPR_MESSAGE,
                             "try",
-                            snippet_block_with_applicability(cx, ex.span, "..", Some(expr.span), &mut applicability)
-                                .to_string(),
+                            snippet_block_with_applicability(cx, ex.span, "..", Some(expr.span), &mut applicability),
                             applicability,
                         );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index ba1135d745a..64aeb27df69 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -7,10 +7,9 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{eq_expr_value, sym};
 use rustc_ast::ast::LitKind;
-use rustc_hir::RustcVersion;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
-use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
+use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, RustcVersion, UnOp};
 use rustc_lint::{LateContext, LateLintPass, Level};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index c1d6cec1b62..c924fba6b5c 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -25,6 +25,12 @@ pub(super) fn check(
         return;
     }
 
+    // If the `as` is from a macro and the casting type is from macro input, whether it is lossless is
+    // dependent on the input
+    if expr.span.from_expansion() && !cast_to_hir.span.eq_ctxt(expr.span) {
+        return;
+    }
+
     span_lint_and_then(
         cx,
         CAST_LOSSLESS,
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 37accff5eaa..dcc439a272c 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -807,7 +807,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// let _ = u16::MAX as usize;
     /// ```
-    #[clippy::version = "1.86.0"]
+    #[clippy::version = "1.89.0"]
     pub CONFUSING_METHOD_TO_NUMERIC_CAST,
     suspicious,
     "casting a primitive method pointer to any integer type"
diff --git a/src/tools/clippy/clippy_lints/src/cloned_ref_to_slice_refs.rs b/src/tools/clippy/clippy_lints/src/cloned_ref_to_slice_refs.rs
index e33a8e0fb74..72ab292ee3c 100644
--- a/src/tools/clippy/clippy_lints/src/cloned_ref_to_slice_refs.rs
+++ b/src/tools/clippy/clippy_lints/src/cloned_ref_to_slice_refs.rs
@@ -37,7 +37,7 @@ declare_clippy_lint! {
     /// let data_ref = &data;
     /// take_slice(slice::from_ref(data_ref));
     /// ```
-    #[clippy::version = "1.87.0"]
+    #[clippy::version = "1.89.0"]
     pub CLONED_REF_TO_SLICE_REFS,
     perf,
     "cloning a reference for slice references"
diff --git a/src/tools/clippy/clippy_lints/src/coerce_container_to_any.rs b/src/tools/clippy/clippy_lints/src/coerce_container_to_any.rs
index 6217fc4c897..2e3acb7748e 100644
--- a/src/tools/clippy/clippy_lints/src/coerce_container_to_any.rs
+++ b/src/tools/clippy/clippy_lints/src/coerce_container_to_any.rs
@@ -41,7 +41,7 @@ declare_clippy_lint! {
     /// // Succeeds since we have a &dyn Any to the inner u32!
     /// assert_eq!(dyn_any_of_u32.downcast_ref::<u32>(), Some(&0u32));
     /// ```
-    #[clippy::version = "1.88.0"]
+    #[clippy::version = "1.89.0"]
     pub COERCE_CONTAINER_TO_ANY,
     nursery,
     "coercing to `&dyn Any` when dereferencing could produce a `dyn Any` without coercion is usually not intended"
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 518535e8c8b..8f1c0296524 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -35,7 +35,7 @@ declare_clippy_lint! {
     /// * [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
     #[clippy::version = "1.35.0"]
     pub COGNITIVE_COMPLEXITY,
-    nursery,
+    restriction,
     "functions that should be split up into multiple functions",
     @eval_always = true
 }
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index 1854d86c53b..e3103e2d301 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -136,6 +136,9 @@ impl CollapsibleIf {
                         return;
                     }
 
+                    // Peel off any parentheses.
+                    let (_, else_block_span, _) = peel_parens(cx.tcx.sess.source_map(), else_.span);
+
                     // Prevent "elseif"
                     // Check that the "else" is followed by whitespace
                     let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
@@ -152,7 +155,7 @@ impl CollapsibleIf {
                             if requires_space { " " } else { "" },
                             snippet_block_with_applicability(
                                 cx,
-                                else_.span,
+                                else_block_span,
                                 "..",
                                 Some(else_block.span),
                                 &mut applicability
@@ -187,7 +190,8 @@ impl CollapsibleIf {
                             .with_leading_whitespace(cx)
                             .into_span()
                     };
-                    let inner_if = inner.span.split_at(2).0;
+                    let (paren_start, inner_if_span, paren_end) = peel_parens(cx.tcx.sess.source_map(), inner.span);
+                    let inner_if = inner_if_span.split_at(2).0;
                     let mut sugg = vec![
                         // Remove the outer then block `{`
                         (then_open_bracket, String::new()),
@@ -196,6 +200,17 @@ impl CollapsibleIf {
                         // Replace inner `if` by `&&`
                         (inner_if, String::from("&&")),
                     ];
+
+                    if !paren_start.is_empty() {
+                        // Remove any leading parentheses '('
+                        sugg.push((paren_start, String::new()));
+                    }
+
+                    if !paren_end.is_empty() {
+                        // Remove any trailing parentheses ')'
+                        sugg.push((paren_end, String::new()));
+                    }
+
                     sugg.extend(parens_around(check));
                     sugg.extend(parens_around(check_inner));
 
@@ -285,3 +300,37 @@ fn span_extract_keyword(sm: &SourceMap, span: Span, keyword: &str) -> Option<Spa
         })
         .next()
 }
+
+/// Peel the parentheses from an `if` expression, e.g. `((if true {} else {}))`.
+fn peel_parens(sm: &SourceMap, mut span: Span) -> (Span, Span, Span) {
+    use crate::rustc_span::Pos;
+
+    let start = span.shrink_to_lo();
+    let end = span.shrink_to_hi();
+
+    let snippet = sm.span_to_snippet(span).unwrap();
+    if let Some((trim_start, _, trim_end)) = peel_parens_str(&snippet) {
+        let mut data = span.data();
+        data.lo = data.lo + BytePos::from_usize(trim_start);
+        data.hi = data.hi - BytePos::from_usize(trim_end);
+        span = data.span();
+    }
+
+    (start.with_hi(span.lo()), span, end.with_lo(span.hi()))
+}
+
+fn peel_parens_str(snippet: &str) -> Option<(usize, &str, usize)> {
+    let trimmed = snippet.trim();
+    if !(trimmed.starts_with('(') && trimmed.ends_with(')')) {
+        return None;
+    }
+
+    let trim_start = (snippet.len() - snippet.trim_start().len()) + 1;
+    let trim_end = (snippet.len() - snippet.trim_end().len()) + 1;
+
+    let inner = snippet.get(trim_start..snippet.len() - trim_end)?;
+    Some(match peel_parens_str(inner) {
+        None => (trim_start, inner, trim_end),
+        Some((start, inner, end)) => (trim_start + start, inner, trim_end + end),
+    })
+}
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 4bd34527d21..4fdb497950f 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -235,9 +235,9 @@ fn lint_branches_sharing_code<'tcx>(
         let cond_snippet = reindent_multiline(&snippet(cx, cond_span, "_"), false, None);
         let cond_indent = indent_of(cx, cond_span);
         let moved_snippet = reindent_multiline(&snippet(cx, span, "_"), true, None);
-        let suggestion = moved_snippet.to_string() + "\n" + &cond_snippet + "{";
+        let suggestion = moved_snippet + "\n" + &cond_snippet + "{";
         let suggestion = reindent_multiline(&suggestion, true, cond_indent);
-        (replace_span, suggestion.to_string())
+        (replace_span, suggestion)
     });
     let end_suggestion = res.end_span(last_block, sm).map(|span| {
         let moved_snipped = reindent_multiline(&snippet(cx, span, "_"), true, None);
@@ -253,7 +253,7 @@ fn lint_branches_sharing_code<'tcx>(
                     .then_some(range.start - 4..range.end)
             })
             .map_or(span, |range| range.with_ctxt(span.ctxt()));
-        (span, suggestion.to_string())
+        (span, suggestion.clone())
     });
 
     let (span, msg, end_span) = match (&start_suggestion, &end_suggestion) {
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index c3f8e02b4c0..e1cb08e361c 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -178,6 +178,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
     crate::format_impl::RECURSIVE_FORMAT_IMPL_INFO,
     crate::format_push_string::FORMAT_PUSH_STRING_INFO,
     crate::formatting::POSSIBLE_MISSING_COMMA_INFO,
+    crate::formatting::POSSIBLE_MISSING_ELSE_INFO,
     crate::formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING_INFO,
     crate::formatting::SUSPICIOUS_ELSE_FORMATTING_INFO,
     crate::formatting::SUSPICIOUS_UNARY_OP_FORMATTING_INFO,
@@ -690,7 +691,6 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
     crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO,
     crate::strings::STRING_LIT_AS_BYTES_INFO,
     crate::strings::STRING_SLICE_INFO,
-    crate::strings::STRING_TO_STRING_INFO,
     crate::strings::STR_TO_STRING_INFO,
     crate::strings::TRIM_SPLIT_WHITESPACE_INFO,
     crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index f41255e54db..df6525ce040 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_hir::attrs::{AttributeKind, ReprAttr};
-use rustc_hir::find_attr;
-use rustc_hir::{HirId, Item, ItemKind};
+use rustc_hir::{HirId, Item, ItemKind, find_attr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, FieldDef};
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 5204f73ea0a..88aebc3e6a1 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -34,6 +34,8 @@ declare_with_version! { DEPRECATED(DEPRECATED_VERSION) = [
     ("clippy::replace_consts", "`min_value` and `max_value` are now deprecated"),
     #[clippy::version = "pre 1.29.0"]
     ("clippy::should_assert_eq", "`assert!(a == b)` can now print the values the same way `assert_eq!(a, b) can"),
+    #[clippy::version = "1.90.0"]
+    ("clippy::string_to_string", "`clippy:implicit_clone` covers those cases"),
     #[clippy::version = "pre 1.29.0"]
     ("clippy::unsafe_vector_initialization", "the suggested alternative could be substantially slower"),
     #[clippy::version = "pre 1.29.0"]
diff --git a/src/tools/clippy/clippy_lints/src/doc/broken_link.rs b/src/tools/clippy/clippy_lints/src/doc/broken_link.rs
index 4af10510023..8878fa9180f 100644
--- a/src/tools/clippy/clippy_lints/src/doc/broken_link.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/broken_link.rs
@@ -19,52 +19,52 @@ pub fn check(cx: &LateContext<'_>, bl: &PullDownBrokenLink<'_>, doc: &str, fragm
 }
 
 fn warn_if_broken_link(cx: &LateContext<'_>, bl: &PullDownBrokenLink<'_>, doc: &str, fragments: &[DocFragment]) {
-    if let Some((span, _)) = source_span_for_markdown_range(cx.tcx, doc, &bl.span, fragments) {
-        let mut len = 0;
+    let mut len = 0;
 
-        // grab raw link data
-        let (_, raw_link) = doc.split_at(bl.span.start);
+    // grab raw link data
+    let (_, raw_link) = doc.split_at(bl.span.start);
 
-        // strip off link text part
-        let raw_link = match raw_link.split_once(']') {
-            None => return,
-            Some((prefix, suffix)) => {
-                len += prefix.len() + 1;
-                suffix
-            },
-        };
+    // strip off link text part
+    let raw_link = match raw_link.split_once(']') {
+        None => return,
+        Some((prefix, suffix)) => {
+            len += prefix.len() + 1;
+            suffix
+        },
+    };
 
-        let raw_link = match raw_link.split_once('(') {
-            None => return,
-            Some((prefix, suffix)) => {
-                if !prefix.is_empty() {
-                    // there is text between ']' and '(' chars, so it is not a valid link
-                    return;
-                }
-                len += prefix.len() + 1;
-                suffix
-            },
-        };
-
-        if raw_link.starts_with("(http") {
-            // reduce chances of false positive reports
-            // by limiting this checking only to http/https links.
-            return;
-        }
-
-        for c in raw_link.chars() {
-            if c == ')' {
-                // it is a valid link
+    let raw_link = match raw_link.split_once('(') {
+        None => return,
+        Some((prefix, suffix)) => {
+            if !prefix.is_empty() {
+                // there is text between ']' and '(' chars, so it is not a valid link
                 return;
             }
+            len += prefix.len() + 1;
+            suffix
+        },
+    };
 
-            if c == '\n' {
-                report_broken_link(cx, span, len);
-                break;
-            }
+    if raw_link.starts_with("(http") {
+        // reduce chances of false positive reports
+        // by limiting this checking only to http/https links.
+        return;
+    }
 
-            len += 1;
+    for c in raw_link.chars() {
+        if c == ')' {
+            // it is a valid link
+            return;
         }
+
+        if c == '\n'
+            && let Some((span, _)) = source_span_for_markdown_range(cx.tcx, doc, &bl.span, fragments)
+        {
+            report_broken_link(cx, span, len);
+            break;
+        }
+
+        len += 1;
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index ea0da0d2467..d27d68d3866 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -662,7 +662,7 @@ declare_clippy_lint! {
     /// /// [^1]: defined here
     /// fn my_fn() {}
     /// ```
-    #[clippy::version = "1.88.0"]
+    #[clippy::version = "1.89.0"]
     pub DOC_SUSPICIOUS_FOOTNOTES,
     suspicious,
     "looks like a link or footnote ref, but with no definition"
diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
index 1e7d1f92fa3..47d91b80e7e 100644
--- a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::AttrStyle;
 use rustc_ast::token::CommentKind;
-use rustc_hir::attrs::AttributeKind;
 use rustc_errors::Applicability;
 use rustc_hir::Attribute;
+use rustc_hir::attrs::AttributeKind;
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
index 32ba696b3ec..674690e7e31 100644
--- a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
@@ -1,5 +1,5 @@
-use rustc_hir::attrs::AttributeKind;
 use rustc_errors::Applicability;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::{Attribute, Item, ItemKind};
 use rustc_lint::LateContext;
 
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index f2757407ba5..e7230ebf8cb 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -93,11 +93,11 @@ impl_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VA
 impl LateLintPass<'_> for EmptyWithBrackets {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         // FIXME: handle `struct $name {}`
-        if let ItemKind::Struct(ident, _, var_data) = &item.kind
+        if let ItemKind::Struct(ident, generics, var_data) = &item.kind
             && !item.span.from_expansion()
             && !ident.span.from_expansion()
             && has_brackets(var_data)
-            && let span_after_ident = item.span.with_lo(ident.span.hi())
+            && let span_after_ident = item.span.with_lo(generics.span.hi())
             && has_no_fields(cx, var_data, span_after_ident)
         {
             span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index ba539d05b6b..e467246741c 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -7,10 +7,9 @@ use clippy_utils::{
     get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
 };
 use rustc_abi::ExternAbi;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_errors::Applicability;
-use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind};
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 5f40e576443..ac61ce705eb 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -1,9 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::indent_of;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_errors::Applicability;
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{Item, ItemKind, find_attr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index d5abaa547e8..84d39dd81c9 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -148,7 +148,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
         .into();
 
         suggestion = match suggestion {
-            Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
+            Sugg::MaybeParen(_) | Sugg::UnOp(UnOp::Neg, _) => Sugg::MaybeParen(op),
             _ => Sugg::NonParen(op),
         };
     }
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index af4202422e4..3359aa60323 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -17,12 +17,11 @@ use rustc_ast::{
     FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
     FormatPlaceholder, FormatTrait,
 };
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::{find_attr,RustcVersion};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
-use rustc_hir::{Expr, ExprKind, LangItem};
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast};
@@ -223,7 +222,7 @@ declare_clippy_lint! {
     /// ```
     ///
     /// [pointer format]: https://doc.rust-lang.org/std/fmt/index.html#formatting-traits
-    #[clippy::version = "1.88.0"]
+    #[clippy::version = "1.89.0"]
     pub POINTER_FORMAT,
     restriction,
     "formatting a pointer"
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index 4b482f7b233..1c751643bec 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -93,6 +93,31 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for an `if` expression followed by either a block or another `if` that
+    /// looks like it should have an `else` between them.
+    ///
+    /// ### Why is this bad?
+    /// This is probably some refactoring remnant, even if the code is correct, it
+    /// might look confusing.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// if foo {
+    /// } { // looks like an `else` is missing here
+    /// }
+    ///
+    /// if foo {
+    /// } if bar { // looks like an `else` is missing here
+    /// }
+    /// ```
+    #[clippy::version = "1.90.0"]
+    pub POSSIBLE_MISSING_ELSE,
+    suspicious,
+    "possibly missing `else`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for possible missing comma in an array. It lints if
     /// an array element is a binary operator expression and it lies on two lines.
     ///
@@ -116,6 +141,7 @@ declare_lint_pass!(Formatting => [
     SUSPICIOUS_ASSIGNMENT_FORMATTING,
     SUSPICIOUS_UNARY_OP_FORMATTING,
     SUSPICIOUS_ELSE_FORMATTING,
+    POSSIBLE_MISSING_ELSE,
     POSSIBLE_MISSING_COMMA
 ]);
 
@@ -307,7 +333,7 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
 
         span_lint_and_note(
             cx,
-            SUSPICIOUS_ELSE_FORMATTING,
+            POSSIBLE_MISSING_ELSE,
             else_span,
             format!("this looks like {looks_like} but the `else` is missing"),
             None,
diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
index 8822b87f92f..a7b0edeb799 100644
--- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
+++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
@@ -1,4 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::SpanRangeExt as _;
+use itertools::Itertools;
 use rustc_errors::Applicability;
 use rustc_hir::Item;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -81,6 +83,14 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
                         "turn these into doc comments by removing one `/`"
                     };
 
+                    // If the comment contains a bare CR (not followed by a LF), do not propose an auto-fix
+                    // as bare CR are not allowed in doc comments.
+                    if span.check_source_text(cx, contains_bare_cr) {
+                        diag.help(msg)
+                            .note("bare CR characters are not allowed in doc comments");
+                        return;
+                    }
+
                     diag.multipart_suggestion(
                         msg,
                         bad_comments
@@ -97,3 +107,8 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
         }
     }
 }
+
+/// Checks if `text` contains any CR not followed by a LF
+fn contains_bare_cr(text: &str) -> bool {
+    text.bytes().tuple_windows().any(|(a, b)| a == b'\r' && b != b'\n')
+}
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 55ca0d9ecb7..8de68bfcb51 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -14,7 +14,7 @@ use clippy_utils::source::snippet_indent;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
-use rustc_hir::attrs::{AttributeKind};
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::find_attr;
 use rustc_span::Symbol;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs
index 25fed0d4dd1..e8afa69b537 100644
--- a/src/tools/clippy/clippy_lints/src/if_not_else.rs
+++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs
@@ -81,7 +81,7 @@ impl LateLintPass<'_> for IfNotElse {
                         e.span,
                         msg,
                         "try",
-                        make_sugg(cx, &cond.kind, cond_inner.span, els.span, "..", Some(e.span)).to_string(),
+                        make_sugg(cx, &cond.kind, cond_inner.span, els.span, "..", Some(e.span)),
                         Applicability::MachineApplicable,
                     ),
                     _ => span_lint_and_help(cx, IF_NOT_ELSE, e.span, msg, None, help),
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index 85ebc830d3b..89988be5875 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -2,14 +2,13 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::Msrv;
 use clippy_utils::{is_in_const_context, is_in_test};
-use rustc_hir::{RustcVersion, StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
-use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, QPath};
+use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, QPath, RustcVersion, StabilityLevel, StableSince};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::DefId;
+use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::{ExpnKind, Span, sym};
 
 declare_clippy_lint! {
@@ -83,16 +82,22 @@ pub struct IncompatibleMsrv {
     msrv: Msrv,
     availability_cache: FxHashMap<(DefId, bool), Availability>,
     check_in_tests: bool,
+    core_crate: Option<CrateNum>,
 }
 
 impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]);
 
 impl IncompatibleMsrv {
-    pub fn new(conf: &'static Conf) -> Self {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
             msrv: conf.msrv,
             availability_cache: FxHashMap::default(),
             check_in_tests: conf.check_incompatible_msrv_in_tests,
+            core_crate: tcx
+                .crates(())
+                .iter()
+                .find(|krate| tcx.crate_name(**krate) == sym::core)
+                .copied(),
         }
     }
 
@@ -140,23 +145,16 @@ impl IncompatibleMsrv {
             // We don't check local items since their MSRV is supposed to always be valid.
             return;
         }
-        if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = span.ctxt().outer_expn_data().kind {
+        let expn_data = span.ctxt().outer_expn_data();
+        if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = expn_data.kind {
             // Desugared expressions get to cheat and stability is ignored.
             // Intentionally not using `.from_expansion()`, since we do still care about macro expansions
             return;
         }
-
         // Functions coming from `core` while expanding a macro such as `assert*!()` get to cheat too: the
         // macros may have existed prior to the checked MSRV, but their expansion with a recent compiler
         // might use recent functions or methods. Compiling with an older compiler would not use those.
-        if span.from_expansion()
-            && cx.tcx.crate_name(def_id.krate) == sym::core
-            && span
-                .ctxt()
-                .outer_expn_data()
-                .macro_def_id
-                .is_some_and(|def_id| cx.tcx.crate_name(def_id.krate) == sym::core)
-        {
+        if Some(def_id.krate) == self.core_crate && expn_data.macro_def_id.map(|did| did.krate) == self.core_crate {
             return;
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 3d131a7825a..8f9f71a1476 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLet;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::ty::is_copy;
-use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local, sym};
+use clippy_utils::{is_lint_allowed, path_to_local};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -71,7 +71,7 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]);
 impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr)
-            && (!expr.span.from_expansion() || is_expn_of(expr.span, sym::if_chain).is_some())
+            && !expr.span.from_expansion()
             && !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id)
             && let found_slices = find_slice_values(cx, let_pat)
             && !found_slices.is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/infallible_try_from.rs b/src/tools/clippy/clippy_lints/src/infallible_try_from.rs
index f7cdf05359a..589c294a678 100644
--- a/src/tools/clippy/clippy_lints/src/infallible_try_from.rs
+++ b/src/tools/clippy/clippy_lints/src/infallible_try_from.rs
@@ -13,7 +13,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     ///
-    /// Infalliable conversions should be implemented via `From` with the blanket conversion.
+    /// Infallible conversions should be implemented via `From` with the blanket conversion.
     ///
     /// ### Example
     /// ```no_run
@@ -35,7 +35,7 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
-    #[clippy::version = "1.88.0"]
+    #[clippy::version = "1.89.0"]
     pub INFALLIBLE_TRY_FROM,
     suspicious,
     "TryFrom with infallible Error type"
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for InfallibleTryFrom {
                     cx,
                     INFALLIBLE_TRY_FROM,
                     span,
-                    "infallible TryFrom impl; consider implementing From, instead",
+                    "infallible TryFrom impl; consider implementing From instead",
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index ee59a4cc8cb..e416ac079d6 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -1,9 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg::DiagExt;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_errors::Applicability;
-use rustc_hir::{TraitFn, TraitItem, TraitItemKind};
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{TraitFn, TraitItem, TraitItemKind, find_attr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
index 1917ca24a05..5b0f95ffc37 100644
--- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
+use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use rustc_errors::Applicability;
 use rustc_hir::{LetStmt, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -30,9 +31,15 @@ impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped {
         if let Some(ty) = local.ty // Ensure that it has a type defined
             && let TyKind::Infer(()) = &ty.kind // that type is '_'
             && local.span.eq_ctxt(ty.span)
-            && !local.span.in_external_macro(cx.tcx.sess.source_map())
+            && let sm = cx.tcx.sess.source_map()
+            && !local.span.in_external_macro(sm)
             && !is_from_proc_macro(cx, ty)
         {
+            let span_to_remove = sm
+                .span_extend_to_prev_char_before(ty.span, ':', true)
+                .with_leading_whitespace(cx)
+                .into_span();
+
             span_lint_and_then(
                 cx,
                 LET_WITH_TYPE_UNDERSCORE,
@@ -40,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped {
                 "variable declared with type underscore",
                 |diag| {
                     diag.span_suggestion_verbose(
-                        ty.span.with_lo(local.pat.span.hi()),
+                        span_to_remove,
                         "remove the explicit type `_` declaration",
                         "",
                         Applicability::MachineApplicable,
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 914aa6b9b80..844bc1b0e39 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -522,7 +522,8 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
     store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
     store.register_late_pass(move |_| Box::new(index_refutable_slice::IndexRefutableSlice::new(conf)));
     store.register_late_pass(|_| Box::<shadow::Shadow>::default());
-    store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
+    let format_args = format_args_storage.clone();
+    store.register_late_pass(move |_| Box::new(unit_types::UnitTypes::new(format_args.clone())));
     store.register_late_pass(move |_| Box::new(loops::Loops::new(conf)));
     store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
     store.register_late_pass(move |_| Box::new(lifetimes::Lifetimes::new(conf)));
@@ -663,7 +664,6 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
     store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop));
     store.register_late_pass(|_| Box::new(strings::StrToString));
-    store.register_late_pass(|_| Box::new(strings::StringToString));
     store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues));
     store.register_late_pass(|_| Box::<vec_init_then_push::VecInitThenPush>::default());
     store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
@@ -796,7 +796,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
     store.register_late_pass(|_| Box::<unconditional_recursion::UnconditionalRecursion>::default());
     store.register_late_pass(move |_| Box::new(pub_underscore_fields::PubUnderscoreFields::new(conf)));
     store.register_late_pass(move |_| Box::new(missing_const_for_thread_local::MissingConstForThreadLocal::new(conf)));
-    store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(conf)));
+    store.register_late_pass(move |tcx| Box::new(incompatible_msrv::IncompatibleMsrv::new(tcx, conf)));
     store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl));
     store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
     store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf)));
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 8a253ae5810..2ccff768097 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -202,7 +202,7 @@ fn all_spans_after_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> Vec<Span> {
                 .iter()
                 .skip_while(|inner| inner.hir_id != stmt.hir_id)
                 .map(stmt_source_span)
-                .chain(if let Some(e) = block.expr { vec![e.span] } else { vec![] })
+                .chain(block.expr.map(|e| e.span))
                 .collect();
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index bf89556fbb6..8989793625a 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -1,11 +1,10 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
 use hir::def::{DefKind, Res};
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{self as hir, AmbigArg};
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{self as hir, AmbigArg, find_attr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index ea6b01a053a..76cb2286477 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::{is_panic, root_macro_call};
-use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg};
+use clippy_utils::{higher, is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, UnOp};
+use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 
@@ -35,7 +35,7 @@ declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
 
 impl<'tcx> LateLintPass<'tcx> for ManualAssert {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if let ExprKind::If(cond, then, None) = expr.kind
+        if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr)
             && !matches!(cond.kind, ExprKind::Let(_))
             && !expr.span.from_expansion()
             && let then = peel_blocks_with_stmt(then)
@@ -51,19 +51,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
             && !is_else_clause(cx.tcx, expr)
         {
             let mut applicability = Applicability::MachineApplicable;
-            let cond = cond.peel_drop_temps();
             let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
             if !comments.is_empty() {
                 comments += "\n";
             }
-            let (cond, not) = match cond.kind {
-                ExprKind::Unary(UnOp::Not, e) => (e, ""),
-                _ => (cond, "!"),
-            };
-            let cond_sugg =
-                sugg::Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "..", &mut applicability).maybe_paren();
+            let cond_sugg = !sugg::Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "..", &mut applicability);
             let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" };
-            let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}");
+            let sugg = format!("assert!({cond_sugg}, {format_args_snip}){semicolon}");
             // we show to the user the suggestion without the comments, but when applying the fix, include the
             // comments in the block
             span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index abd1ac954cd..ba1ad599e11 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                             format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
                         };
 
-                        let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)).to_string();
+                        let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
 
                         diag.multipart_suggestion(
                             "make the function `async` and return the output of the future directly",
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 6b0f7446849..0d783fde331 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -4,12 +4,11 @@ use clippy_utils::is_doc_hidden;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_indent;
 use itertools::Itertools;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData};
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData, find_attr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index 6a76c6cedd0..82d5310663e 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -1,11 +1,16 @@
+use std::ops::ControlFlow;
+
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::HirNode;
-use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_context};
-use clippy_utils::{is_refutable, peel_blocks};
+use clippy_utils::source::{indent_of, reindent_multiline, snippet, snippet_block_with_context, snippet_with_context};
+use clippy_utils::{is_expr_identity_of_pat, is_refutable, peel_blocks};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, Expr, ExprKind, Node, PatKind, StmtKind};
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_path, walk_stmt};
+use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, Node, PatKind, Path, Stmt, StmtKind};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
 use super::MATCH_SINGLE_BINDING;
 
@@ -26,9 +31,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
     let match_body = peel_blocks(arms[0].body);
     let mut app = Applicability::MaybeIncorrect;
     let ctxt = expr.span.ctxt();
-    let mut snippet_body = snippet_block_with_context(cx, match_body.span, ctxt, "..", Some(expr.span), &mut app)
-        .0
-        .to_string();
+    let mut snippet_body = snippet_block_with_context(cx, match_body.span, ctxt, "..", Some(expr.span), &mut app).0;
 
     // Do we need to add ';' to suggestion ?
     if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
@@ -50,10 +53,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                         cx,
                         (ex, expr),
                         (bind_names, matched_vars),
-                        &snippet_body,
+                        snippet_body,
                         &mut app,
                         Some(span),
                         true,
+                        is_var_binding_used_later(cx, expr, &arms[0]),
                     );
 
                     span_lint_and_sugg(
@@ -78,15 +82,28 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                         snippet_with_context(cx, pat_span, ctxt, "..", &mut app).0
                     ),
                 ),
+                None if is_expr_identity_of_pat(cx, arms[0].pat, ex, false) => {
+                    span_lint_and_sugg(
+                        cx,
+                        MATCH_SINGLE_BINDING,
+                        expr.span,
+                        "this match could be replaced by its body itself",
+                        "consider using the match body instead",
+                        snippet_body,
+                        Applicability::MachineApplicable,
+                    );
+                    return;
+                },
                 None => {
                     let sugg = sugg_with_curlies(
                         cx,
                         (ex, expr),
                         (bind_names, matched_vars),
-                        &snippet_body,
+                        snippet_body,
                         &mut app,
                         None,
                         true,
+                        is_var_binding_used_later(cx, expr, &arms[0]),
                     );
                     (expr.span, sugg)
                 },
@@ -108,10 +125,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                     cx,
                     (ex, expr),
                     (bind_names, matched_vars),
-                    &snippet_body,
+                    snippet_body,
                     &mut app,
                     None,
                     false,
+                    true,
                 );
 
                 span_lint_and_sugg(
@@ -139,6 +157,125 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
     }
 }
 
+struct VarBindingVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    identifiers: FxHashSet<Symbol>,
+}
+
+impl<'tcx> Visitor<'tcx> for VarBindingVisitor<'_, 'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) -> Self::Result {
+        if let Res::Local(_) = path.res
+            && let [segment] = path.segments
+            && self.identifiers.contains(&segment.ident.name)
+        {
+            return ControlFlow::Break(());
+        }
+
+        walk_path(self, path)
+    }
+
+    fn visit_block(&mut self, block: &'tcx Block<'tcx>) -> Self::Result {
+        let before = self.identifiers.clone();
+        walk_block(self, block)?;
+        self.identifiers = before;
+        ControlFlow::Continue(())
+    }
+
+    fn visit_stmt(&mut self, stmt: &'tcx Stmt<'tcx>) -> Self::Result {
+        if let StmtKind::Let(let_stmt) = stmt.kind {
+            if let Some(init) = let_stmt.init {
+                self.visit_expr(init)?;
+            }
+
+            let_stmt.pat.each_binding(|_, _, _, ident| {
+                self.identifiers.remove(&ident.name);
+            });
+        }
+        walk_stmt(self, stmt)
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {
+        match expr.kind {
+            ExprKind::If(
+                Expr {
+                    kind: ExprKind::Let(let_expr),
+                    ..
+                },
+                then,
+                else_,
+            ) => {
+                self.visit_expr(let_expr.init)?;
+                let before = self.identifiers.clone();
+                let_expr.pat.each_binding(|_, _, _, ident| {
+                    self.identifiers.remove(&ident.name);
+                });
+
+                self.visit_expr(then)?;
+                self.identifiers = before;
+                if let Some(else_) = else_ {
+                    self.visit_expr(else_)?;
+                }
+                ControlFlow::Continue(())
+            },
+            ExprKind::Closure(closure) => {
+                let body = self.cx.tcx.hir_body(closure.body);
+                let before = self.identifiers.clone();
+                for param in body.params {
+                    param.pat.each_binding(|_, _, _, ident| {
+                        self.identifiers.remove(&ident.name);
+                    });
+                }
+                self.visit_expr(body.value)?;
+                self.identifiers = before;
+                ControlFlow::Continue(())
+            },
+            ExprKind::Match(expr, arms, _) => {
+                self.visit_expr(expr)?;
+                for arm in arms {
+                    let before = self.identifiers.clone();
+                    arm.pat.each_binding(|_, _, _, ident| {
+                        self.identifiers.remove(&ident.name);
+                    });
+                    if let Some(guard) = arm.guard {
+                        self.visit_expr(guard)?;
+                    }
+                    self.visit_expr(arm.body)?;
+                    self.identifiers = before;
+                }
+                ControlFlow::Continue(())
+            },
+            _ => walk_expr(self, expr),
+        }
+    }
+}
+
+fn is_var_binding_used_later(cx: &LateContext<'_>, expr: &Expr<'_>, arm: &Arm<'_>) -> bool {
+    let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id) else {
+        return false;
+    };
+    let Node::Block(block) = cx.tcx.parent_hir_node(stmt.hir_id) else {
+        return false;
+    };
+
+    let mut identifiers = FxHashSet::default();
+    arm.pat.each_binding(|_, _, _, ident| {
+        identifiers.insert(ident.name);
+    });
+
+    let mut visitor = VarBindingVisitor { cx, identifiers };
+    block
+        .stmts
+        .iter()
+        .skip_while(|s| s.hir_id != stmt.hir_id)
+        .skip(1)
+        .any(|stmt| matches!(visitor.visit_stmt(stmt), ControlFlow::Break(())))
+        || block
+            .expr
+            .is_some_and(|expr| matches!(visitor.visit_expr(expr), ControlFlow::Break(())))
+}
+
 /// Returns true if the `ex` match expression is in a local (`let`) or assign expression
 fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<AssignmentExpr> {
     if let Node::Expr(parent_arm_expr) = cx.tcx.parent_hir_node(ex.hir_id) {
@@ -161,47 +298,66 @@ fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<Ass
     None
 }
 
-fn expr_parent_requires_curlies<'a>(cx: &LateContext<'a>, match_expr: &Expr<'a>) -> bool {
+fn expr_in_nested_block(cx: &LateContext<'_>, match_expr: &Expr<'_>) -> bool {
+    if let Node::Block(block) = cx.tcx.parent_hir_node(match_expr.hir_id) {
+        return block
+            .expr
+            .map_or_else(|| matches!(block.stmts, [_]), |_| block.stmts.is_empty());
+    }
+    false
+}
+
+fn expr_must_have_curlies(cx: &LateContext<'_>, match_expr: &Expr<'_>) -> bool {
     let parent = cx.tcx.parent_hir_node(match_expr.hir_id);
-    matches!(
-        parent,
-        Node::Expr(Expr {
-            kind: ExprKind::Closure { .. },
-            ..
-        }) | Node::AnonConst(..)
+    if let Node::Expr(Expr {
+        kind: ExprKind::Closure(..) | ExprKind::Binary(..),
+        ..
+    })
+    | Node::AnonConst(..) = parent
+    {
+        return true;
+    }
+
+    if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id)
+        && let ExprKind::Match(..) = arm.body.kind
+    {
+        return true;
+    }
+
+    false
+}
+
+fn indent_of_nth_line(snippet: &str, nth: usize) -> Option<usize> {
+    snippet
+        .lines()
+        .nth(nth)
+        .and_then(|s| s.find(|c: char| !c.is_whitespace()))
+}
+
+fn reindent_snippet_if_in_block(snippet_body: &str, has_assignment: bool) -> String {
+    if has_assignment || !snippet_body.starts_with('{') {
+        return reindent_multiline(snippet_body, true, indent_of_nth_line(snippet_body, 1));
+    }
+
+    let snippet_body = snippet_body.trim_start_matches('{').trim_end_matches('}').trim();
+    reindent_multiline(
+        snippet_body,
+        false,
+        indent_of_nth_line(snippet_body, 0).map(|indent| indent.saturating_sub(4)),
     )
 }
 
+#[expect(clippy::too_many_arguments)]
 fn sugg_with_curlies<'a>(
     cx: &LateContext<'a>,
     (ex, match_expr): (&Expr<'a>, &Expr<'a>),
     (bind_names, matched_vars): (Span, Span),
-    snippet_body: &str,
+    mut snippet_body: String,
     applicability: &mut Applicability,
     assignment: Option<Span>,
     needs_var_binding: bool,
+    is_var_binding_used_later: bool,
 ) -> String {
-    let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0));
-
-    let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
-    if expr_parent_requires_curlies(cx, match_expr) {
-        cbrace_end = format!("\n{indent}}}");
-        // Fix body indent due to the closure
-        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-        cbrace_start = format!("{{\n{indent}");
-    }
-
-    // If the parent is already an arm, and the body is another match statement,
-    // we need curly braces around suggestion
-    if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id)
-        && let ExprKind::Match(..) = arm.body.kind
-    {
-        cbrace_end = format!("\n{indent}}}");
-        // Fix body indent due to the match
-        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-        cbrace_start = format!("{{\n{indent}");
-    }
-
     let assignment_str = assignment.map_or_else(String::new, |span| {
         let mut s = snippet(cx, span, "..").to_string();
         s.push_str(" = ");
@@ -221,5 +377,17 @@ fn sugg_with_curlies<'a>(
             .to_string()
     };
 
+    let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0));
+    let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
+    if !expr_in_nested_block(cx, match_expr)
+        && ((needs_var_binding && is_var_binding_used_later) || expr_must_have_curlies(cx, match_expr))
+    {
+        cbrace_end = format!("\n{indent}}}");
+        // Fix body indent due to the closure
+        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
+        cbrace_start = format!("{{\n{indent}");
+        snippet_body = reindent_snippet_if_in_block(&snippet_body, !assignment_str.is_empty());
+    }
+
     format!("{cbrace_start}{scrutinee};\n{indent}{assignment_str}{snippet_body}{cbrace_end}")
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 7e530e98ac4..bcf079b7007 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -112,9 +112,7 @@ fn report_single_pattern(
         let (sugg, help) = if is_unit_expr(arm.body) {
             (String::new(), "`match` expression can be removed")
         } else {
-            let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app)
-                .0
-                .to_string();
+            let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app).0;
             if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
                 && let StmtKind::Expr(_) = stmt.kind
                 && match arm.body.kind {
@@ -127,7 +125,7 @@ fn report_single_pattern(
             (sugg, "try")
         };
         span_lint_and_then(cx, lint, expr.span, msg, |diag| {
-            diag.span_suggestion(expr.span, help, sugg.to_string(), app);
+            diag.span_suggestion(expr.span, help, sugg, app);
             note(diag);
         });
         return;
@@ -188,7 +186,7 @@ fn report_single_pattern(
     };
 
     span_lint_and_then(cx, lint, expr.span, msg, |diag| {
-        diag.span_suggestion(expr.span, "try", sugg.to_string(), app);
+        diag.span_suggestion(expr.span, "try", sugg, app);
         note(diag);
     });
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index efa8cee58df..8a976d1b4dc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -40,14 +40,12 @@ pub fn check(cx: &LateContext<'_>, method_name: Symbol, expr: &hir::Expr<'_>, re
 }
 
 /// Returns true if the named method can be used to clone the receiver.
-/// Note that `to_string` is not flagged by `implicit_clone`. So other lints that call
-/// `is_clone_like` and that do flag `to_string` must handle it separately. See, e.g.,
-/// `is_to_owned_like` in `unnecessary_to_owned.rs`.
 pub fn is_clone_like(cx: &LateContext<'_>, method_name: Symbol, method_def_id: hir::def_id::DefId) -> bool {
     match method_name {
         sym::to_os_string => is_diag_item_method(cx, method_def_id, sym::OsStr),
         sym::to_owned => is_diag_trait_item(cx, method_def_id, sym::ToOwned),
         sym::to_path_buf => is_diag_item_method(cx, method_def_id, sym::Path),
+        sym::to_string => is_diag_trait_item(cx, method_def_id, sym::ToString),
         sym::to_vec => cx
             .tcx
             .impl_of_assoc(method_def_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/ip_constant.rs b/src/tools/clippy/clippy_lints/src/methods/ip_constant.rs
index 83803fba6a1..a2ac4e54334 100644
--- a/src/tools/clippy/clippy_lints/src/methods/ip_constant.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/ip_constant.rs
@@ -1,7 +1,7 @@
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, QPath, Ty, TyKind};
+use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::sym;
 use smallvec::SmallVec;
@@ -9,13 +9,8 @@ use smallvec::SmallVec;
 use super::IP_CONSTANT;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>]) {
-    if let ExprKind::Path(QPath::TypeRelative(
-        Ty {
-            kind: TyKind::Path(QPath::Resolved(_, func_path)),
-            ..
-        },
-        p,
-    )) = func.kind
+    if let ExprKind::Path(QPath::TypeRelative(ty, p)) = func.kind
+        && let TyKind::Path(QPath::Resolved(_, func_path)) = ty.kind
         && p.ident.name == sym::new
         && let Some(func_def_id) = func_path.res.opt_def_id()
         && matches!(
@@ -40,13 +35,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args
             _ => return,
         };
 
+        let mut sugg = vec![(expr.span.with_lo(p.ident.span.lo()), constant_name.to_owned())];
+        let before_span = expr.span.shrink_to_lo().until(ty.span);
+        if !before_span.is_empty() {
+            // Remove everything before the type name
+            sugg.push((before_span, String::new()));
+        }
+
         span_lint_and_then(cx, IP_CONSTANT, expr.span, "hand-coded well-known IP address", |diag| {
-            diag.span_suggestion_verbose(
-                expr.span.with_lo(p.ident.span.lo()),
-                "use",
-                constant_name,
-                Applicability::MachineApplicable,
-            );
+            diag.multipart_suggestion_verbose("use", sugg, Applicability::MachineApplicable);
         });
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index c0366765234..83e565562af 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -2,14 +2,15 @@ use std::iter::once;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
+use clippy_utils::ty::{ExprFnSig, expr_sig, ty_sig};
 use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core, sym};
 
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
-use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::HirId;
 use rustc_hir::{Expr, ExprKind, Node};
 use rustc_lint::LateContext;
+use rustc_middle::ty::Binder;
 use rustc_span::Symbol;
 
 use super::{ITER_ON_EMPTY_COLLECTIONS, ITER_ON_SINGLE_ITEMS};
@@ -32,24 +33,34 @@ impl IterType {
 
 fn is_arg_ty_unified_in_fn<'tcx>(
     cx: &LateContext<'tcx>,
-    fn_id: DefId,
+    fn_sig: ExprFnSig<'tcx>,
     arg_id: HirId,
     args: impl IntoIterator<Item = &'tcx Expr<'tcx>>,
+    is_method: bool,
 ) -> bool {
-    let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity();
     let arg_id_in_args = args.into_iter().position(|e| e.hir_id == arg_id).unwrap();
-    let arg_ty_in_args = fn_sig.input(arg_id_in_args).skip_binder();
+    let Some(arg_ty_in_args) = fn_sig.input(arg_id_in_args).map(Binder::skip_binder) else {
+        return false;
+    };
 
-    cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| {
-        clause
-            .as_projection_clause()
-            .and_then(|p| p.map_bound(|p| p.term.as_type()).transpose())
-            .is_some_and(|ty| ty.skip_binder() == arg_ty_in_args)
-    }) || fn_sig
-        .inputs()
-        .iter()
-        .enumerate()
-        .any(|(i, ty)| i != arg_id_in_args && ty.skip_binder().walk().any(|arg| arg.as_type() == Some(arg_ty_in_args)))
+    fn_sig
+        .predicates_id()
+        .map(|def_id| cx.tcx.predicates_of(def_id))
+        .is_some_and(|generics| {
+            generics.predicates.iter().any(|(clause, _)| {
+                clause
+                    .as_projection_clause()
+                    .and_then(|p| p.map_bound(|p| p.term.as_type()).transpose())
+                    .is_some_and(|ty| ty.skip_binder() == arg_ty_in_args)
+            })
+        })
+        || (!is_method
+            && fn_sig.input(arg_id_in_args).is_some_and(|binder| {
+                binder
+                    .skip_binder()
+                    .walk()
+                    .any(|arg| arg.as_type() == Some(arg_ty_in_args))
+            }))
 }
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: Symbol, recv: &'tcx Expr<'tcx>) {
@@ -70,25 +81,16 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method
     let is_unified = match get_expr_use_or_unification_node(cx.tcx, expr) {
         Some((Node::Expr(parent), child_id)) => match parent.kind {
             ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id == child_id => false,
-            ExprKind::Call(
-                Expr {
-                    kind: ExprKind::Path(path),
-                    hir_id,
-                    ..
-                },
-                args,
-            ) => cx
+            ExprKind::Call(recv, args) => {
+                expr_sig(cx, recv).is_some_and(|fn_sig| is_arg_ty_unified_in_fn(cx, fn_sig, child_id, args, false))
+            },
+            ExprKind::MethodCall(_name, recv, args, _span) => cx
                 .typeck_results()
-                .qpath_res(path, *hir_id)
-                .opt_def_id()
-                .filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like())
-                .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, child_id, args)),
-            ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn(
-                cx,
-                cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(),
-                child_id,
-                once(recv).chain(args.iter()),
-            ),
+                .type_dependent_def_id(parent.hir_id)
+                .and_then(|def_id| ty_sig(cx, cx.tcx.type_of(def_id).instantiate_identity()))
+                .is_some_and(|fn_sig| {
+                    is_arg_ty_unified_in_fn(cx, fn_sig, child_id, once(recv).chain(args.iter()), true)
+                }),
             ExprKind::If(_, _, _)
             | ExprKind::Match(_, _, _)
             | ExprKind::Closure(_)
@@ -96,7 +98,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method
             | ExprKind::Break(_, _) => true,
             _ => false,
         },
-        Some((Node::Stmt(_) | Node::LetStmt(_), _)) => false,
+        Some((Node::LetStmt(let_stmt), _)) => let_stmt.ty.is_some(),
+        Some((Node::Stmt(_), _)) => false,
         _ => true,
     };
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index bcd54557331..49ca81dafc2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -5450,7 +5450,7 @@ impl Methods {
                         implicit_clone::check(cx, name, expr, recv);
                     }
                 },
-                (sym::to_os_string | sym::to_path_buf | sym::to_vec, []) => {
+                (sym::to_os_string | sym::to_path_buf | sym::to_string | sym::to_vec, []) => {
                     implicit_clone::check(cx, name, expr, recv);
                 },
                 (sym::type_id, []) => {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
index 4a9007c607c..1f5e3de6e7a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
@@ -109,10 +109,16 @@ pub(super) fn check<'a>(
         );
 
         let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) {
-            match parent_expr.kind {
-                ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_paren(),
-                ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_paren(),
-                _ => binop,
+            if parent_expr.span.eq_ctxt(expr.span) {
+                match parent_expr.kind {
+                    ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_paren(),
+                    ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_paren(),
+                    _ => binop,
+                }
+            } else {
+                // if our parent expr is created by a macro, then it should be the one taking care of
+                // parenthesising us if necessary
+                binop
             }
         } else {
             binop
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index 1de9f6ab497..fa9d5332ff4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -199,44 +199,50 @@ pub(super) fn check<'tcx>(
     is_unstable: bool,
 ) {
     match detect_lint(cx, expr, recv, arg) {
-        Some(LintTrigger::SortByKey(trigger)) => span_lint_and_sugg(
-            cx,
-            UNNECESSARY_SORT_BY,
-            expr.span,
-            "consider using `sort_by_key`",
-            "try",
-            format!(
-                "{}.sort{}_by_key(|{}| {})",
-                trigger.vec_name,
-                if is_unstable { "_unstable" } else { "" },
-                trigger.closure_arg,
-                if let Some(std_or_core) = std_or_core(cx)
-                    && trigger.reverse
-                {
-                    format!("{}::cmp::Reverse({})", std_or_core, trigger.closure_body)
+        Some(LintTrigger::SortByKey(trigger)) => {
+            let method = if is_unstable {
+                "sort_unstable_by_key"
+            } else {
+                "sort_by_key"
+            };
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_SORT_BY,
+                expr.span,
+                format!("consider using `{method}`"),
+                "try",
+                format!(
+                    "{}.{}(|{}| {})",
+                    trigger.vec_name,
+                    method,
+                    trigger.closure_arg,
+                    if let Some(std_or_core) = std_or_core(cx)
+                        && trigger.reverse
+                    {
+                        format!("{}::cmp::Reverse({})", std_or_core, trigger.closure_body)
+                    } else {
+                        trigger.closure_body
+                    },
+                ),
+                if trigger.reverse {
+                    Applicability::MaybeIncorrect
                 } else {
-                    trigger.closure_body.to_string()
+                    Applicability::MachineApplicable
                 },
-            ),
-            if trigger.reverse {
-                Applicability::MaybeIncorrect
-            } else {
-                Applicability::MachineApplicable
-            },
-        ),
-        Some(LintTrigger::Sort(trigger)) => span_lint_and_sugg(
-            cx,
-            UNNECESSARY_SORT_BY,
-            expr.span,
-            "consider using `sort`",
-            "try",
-            format!(
-                "{}.sort{}()",
-                trigger.vec_name,
-                if is_unstable { "_unstable" } else { "" },
-            ),
-            Applicability::MachineApplicable,
-        ),
+            );
+        },
+        Some(LintTrigger::Sort(trigger)) => {
+            let method = if is_unstable { "sort_unstable" } else { "sort" };
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_SORT_BY,
+                expr.span,
+                format!("consider using `{method}`"),
+                "try",
+                format!("{}.{}()", trigger.vec_name, method),
+                Applicability::MachineApplicable,
+            );
+        },
         None => {},
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 54f45263275..c1f4904af7c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -621,8 +621,8 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id:
 /// Returns true if the named method can be used to convert the receiver to its "owned"
 /// representation.
 fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name: Symbol, method_def_id: DefId) -> bool {
-    is_clone_like(cx, method_name, method_def_id)
-        || is_cow_into_owned(cx, method_name, method_def_id)
+    is_cow_into_owned(cx, method_name, method_def_id)
+        || (method_name != sym::to_string && is_clone_like(cx, method_name, method_def_id))
         || is_to_string_on_string_like(cx, call_expr, method_name, method_def_id)
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
index 99f01c8001a..dbce29a8631 100644
--- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -4,10 +4,14 @@ use clippy_utils::is_from_proc_macro;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{Visitor, walk_item, walk_trait_item};
-use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem, UsePath};
+use rustc_hir::{
+    GenericParamKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem,
+    UsePath,
+};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::Span;
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 
 declare_clippy_lint! {
@@ -32,6 +36,10 @@ declare_clippy_lint! {
     ///     let title = movie.title;
     /// }
     /// ```
+    ///
+    /// ### Limitations
+    /// Trait implementations which use the same function or parameter name as the trait declaration will
+    /// not be warned about, even if the name is below the configured limit.
     #[clippy::version = "1.72.0"]
     pub MIN_IDENT_CHARS,
     restriction,
@@ -76,6 +84,18 @@ impl LateLintPass<'_> for MinIdentChars {
             return;
         }
 
+        // If the function is declared but not defined in a trait, check_pat isn't called so we need to
+        // check this explicitly
+        if matches!(&item.kind, rustc_hir::TraitItemKind::Fn(_, _)) {
+            let param_names = cx.tcx.fn_arg_idents(item.owner_id.to_def_id());
+            for ident in param_names.iter().flatten() {
+                let str = ident.as_str();
+                if self.is_ident_too_short(cx, str, ident.span) {
+                    emit_min_ident_chars(self, cx, str, ident.span);
+                }
+            }
+        }
+
         walk_trait_item(&mut IdentVisitor { conf: self, cx }, item);
     }
 
@@ -84,6 +104,7 @@ impl LateLintPass<'_> for MinIdentChars {
         if let PatKind::Binding(_, _, ident, ..) = pat.kind
             && let str = ident.as_str()
             && self.is_ident_too_short(cx, str, ident.span)
+            && is_not_in_trait_impl(cx, pat, ident)
         {
             emit_min_ident_chars(self, cx, str, ident.span);
         }
@@ -118,6 +139,11 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
 
         let str = ident.as_str();
         if conf.is_ident_too_short(cx, str, ident.span) {
+            // Check whether the node is part of a `impl` for a trait.
+            if matches!(cx.tcx.parent_hir_node(hir_id), Node::TraitRef(_)) {
+                return;
+            }
+
             // Check whether the node is part of a `use` statement. We don't want to emit a warning if the user
             // has no control over the type.
             let usenode = opt_as_use_node(node).or_else(|| {
@@ -201,3 +227,52 @@ fn opt_as_use_node(node: Node<'_>) -> Option<&'_ UsePath<'_>> {
         None
     }
 }
+
+/// Check if a pattern is a function param in an impl block for a trait and that the param name is
+/// the same than in the trait definition.
+fn is_not_in_trait_impl(cx: &LateContext<'_>, pat: &Pat<'_>, ident: Ident) -> bool {
+    let parent_node = cx.tcx.parent_hir_node(pat.hir_id);
+    if !matches!(parent_node, Node::Param(_)) {
+        return true;
+    }
+
+    for (_, parent_node) in cx.tcx.hir_parent_iter(pat.hir_id) {
+        if let Node::ImplItem(impl_item) = parent_node
+            && matches!(impl_item.kind, ImplItemKind::Fn(_, _))
+        {
+            let impl_parent_node = cx.tcx.parent_hir_node(impl_item.hir_id());
+            if let Node::Item(parent_item) = impl_parent_node
+                && let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = &parent_item.kind
+                && let Some(name) = get_param_name(impl_item, cx, ident)
+            {
+                return name != ident.name;
+            }
+
+            return true;
+        }
+    }
+
+    true
+}
+
+fn get_param_name(impl_item: &ImplItem<'_>, cx: &LateContext<'_>, ident: Ident) -> Option<Symbol> {
+    if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
+        let trait_param_names = cx.tcx.fn_arg_idents(trait_item_def_id);
+
+        let ImplItemKind::Fn(_, body_id) = impl_item.kind else {
+            return None;
+        };
+
+        if let Some(param_index) = cx
+            .tcx
+            .hir_body_param_idents(body_id)
+            .position(|param_ident| param_ident.is_some_and(|param_ident| param_ident.span == ident.span))
+            && let Some(trait_param_name) = trait_param_names.get(param_index)
+            && let Some(trait_param_ident) = trait_param_name
+        {
+            return Some(trait_param_ident.name);
+        }
+    }
+
+    None
+}
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index c637fb247ff..d02952eb487 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -1,8 +1,7 @@
 use clippy_utils::diagnostics::span_lint;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, Attribute};
+use rustc_hir::{self as hir, Attribute, find_attr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::AssocItemContainer;
 use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index b3aa1a7286a..fa5afcc0087 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
     SpanlessEq, get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt,
-    is_receiver_of_method_call, peel_blocks, peel_blocks_with_stmt, span_extract_comment, sym,
+    is_receiver_of_method_call, peel_blocks, peel_blocks_with_stmt, span_contains_comment, sym,
 };
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -128,14 +128,13 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool {
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if e.span.from_expansion() || !span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() {
-            return;
-        }
-        if let Some(higher::If {
-            cond,
-            then,
-            r#else: Some(r#else),
-        }) = higher::If::hir(e)
+        if !e.span.from_expansion()
+            && let Some(higher::If {
+                cond,
+                then,
+                r#else: Some(else_expr),
+            }) = higher::If::hir(e)
+            && !span_contains_comment(cx.tcx.sess.source_map(), e.span)
         {
             let reduce = |ret, not| {
                 let mut applicability = Applicability::MachineApplicable;
@@ -167,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                     applicability,
                 );
             };
-            if let Some((a, b)) = fetch_bool_block(then).and_then(|a| Some((a, fetch_bool_block(r#else)?))) {
+            if let Some((a, b)) = fetch_bool_block(then).and_then(|a| Some((a, fetch_bool_block(else_expr)?))) {
                 match (a, b) {
                     (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => {
                         span_lint(
@@ -193,7 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                 }
             }
             if let Some((lhs_a, a)) = fetch_assign(then)
-                && let Some((lhs_b, b)) = fetch_assign(r#else)
+                && let Some((lhs_b, b)) = fetch_assign(else_expr)
                 && SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b)
             {
                 let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 7b057998063..32ded96c123 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -311,9 +311,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 
 /// Functions marked with these attributes must have the exact signature.
 pub(crate) fn requires_exact_signature(attrs: &[Attribute]) -> bool {
-    attrs.iter().any(|attr| {
-        attr.is_proc_macro_attr()
-    })
+    attrs.iter().any(Attribute::is_proc_macro_attr)
 }
 
 #[derive(Default)]
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
index 791bbbe30a8..daa2c287794 100644
--- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use rustc_abi::ExternAbi;
-use rustc_hir::attrs::AttributeKind;
 use rustc_errors::Applicability;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::{Attribute, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
index abee3c44c5a..7ecde40aee0 100644
--- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
+++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
@@ -49,7 +49,7 @@ declare_clippy_lint! {
 /// Some functions could be replaced as well if we have replaced `Lazy` to `LazyLock`,
 /// therefore after suggesting replace the type, we need to make sure the function calls can be
 /// replaced, otherwise the suggestions cannot be applied thus the applicability should be
-/// `Unspecified` or `MaybeIncorret`.
+/// [`Applicability::Unspecified`] or [`Applicability::MaybeIncorrect`].
 static FUNCTION_REPLACEMENTS: &[(&str, Option<&str>)] = &[
     ("once_cell::sync::Lazy::force", Some("std::sync::LazyLock::force")),
     ("once_cell::sync::Lazy::get", None), // `std::sync::LazyLock::get` is experimental
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 9487cec87ef..3483f3081a5 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -127,7 +127,8 @@ fn try_get_option_occurrence<'tcx>(
     if_else: &'tcx Expr<'_>,
 ) -> Option<OptionOccurrence> {
     let cond_expr = match expr.kind {
-        ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
+        ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
+        ExprKind::Unary(UnOp::Deref, inner_expr) if !cx.typeck_results().expr_ty(inner_expr).is_raw_ptr() => inner_expr,
         _ => expr,
     };
     let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
@@ -223,8 +224,8 @@ fn try_get_option_occurrence<'tcx>(
 
         let mut app = Applicability::Unspecified;
 
-        let (none_body, is_argless_call) = match none_body.kind {
-            ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true),
+        let (none_body, can_omit_arg) = match none_body.kind {
+            ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() && !is_result => (call_expr, true),
             _ => (none_body, false),
         };
 
@@ -241,7 +242,7 @@ fn try_get_option_occurrence<'tcx>(
             ),
             none_expr: format!(
                 "{}{}",
-                if method_sugg == "map_or" || is_argless_call {
+                if method_sugg == "map_or" || can_omit_arg {
                     ""
                 } else if is_result {
                     "|_| "
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 303c5dfed89..d7b4a03aa53 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -5,13 +5,12 @@ use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy};
 use clippy_utils::{is_self, is_self_ty};
 use core::ops::ControlFlow;
 use rustc_abi::ExternAbi;
-use rustc_hir::attrs::{AttributeKind, InlineAttr};
-use rustc_hir::find_attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::attrs::{AttributeKind, InlineAttr};
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
+use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind, find_attr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
 use rustc_middle::ty::layout::LayoutOf;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs
index a3be16ed858..79353dc9247 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_else.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs
@@ -97,7 +97,7 @@ impl EarlyLintPass for RedundantElse {
             els.span.with_lo(then.span.hi()),
             "redundant else block",
             "remove the `else` block and move the contents out",
-            make_sugg(cx, els.span, "..", Some(expr.span)).to_string(),
+            make_sugg(cx, els.span, "..", Some(expr.span)),
             app,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index 2cdb8ef3a65..b057396034c 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -1,11 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::{nth_arg, return_ty};
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
+use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind, find_attr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index f6c128d4c52..db91c57b181 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -102,7 +102,7 @@ impl SemicolonBlock {
     }
 
     fn semicolon_outside_block(&self, cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>) {
-        let insert_span = block.span.with_lo(block.span.hi());
+        let insert_span = block.span.shrink_to_hi();
 
         // For macro call semicolon statements (`mac!();`), the statement's span does not actually
         // include the semicolon itself, so use `mac_call_stmt_semi_span`, which finds the semicolon
@@ -144,28 +144,20 @@ impl LateLintPass<'_> for SemicolonBlock {
                 kind: ExprKind::Block(block, _),
                 ..
             }) if !block.span.from_expansion() && stmt.span.contains(block.span) => {
-                let Block {
-                    expr: None,
-                    stmts: [.., stmt],
-                    ..
-                } = block
-                else {
-                    return;
-                };
-                let &Stmt {
-                    kind: StmtKind::Semi(expr),
-                    ..
-                } = stmt
-                else {
-                    return;
-                };
-                self.semicolon_outside_block(cx, block, expr);
+                if block.expr.is_none()
+                    && let [.., stmt] = block.stmts
+                    && let StmtKind::Semi(expr) = stmt.kind
+                {
+                    self.semicolon_outside_block(cx, block, expr);
+                }
             },
             StmtKind::Semi(Expr {
-                kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
+                kind: ExprKind::Block(block, _),
                 ..
             }) if !block.span.from_expansion() => {
-                self.semicolon_inside_block(cx, block, tail, stmt.span);
+                if let Some(tail) = block.expr {
+                    self.semicolon_inside_block(cx, block, tail, stmt.span);
+                }
             },
             _ => (),
         }
@@ -173,9 +165,5 @@ impl LateLintPass<'_> for SemicolonBlock {
 }
 
 fn get_line(cx: &LateContext<'_>, span: Span) -> Option<usize> {
-    if let Ok(line) = cx.sess().source_map().lookup_line(span.lo()) {
-        return Some(line.line);
-    }
-
-    None
+    cx.sess().source_map().lookup_line(span.lo()).ok().map(|line| line.line)
 }
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index 50c44a8e75c..e9534bc63a6 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -2,11 +2,10 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::msrvs::Msrv;
-use rustc_hir::{StabilityLevel, StableSince};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Block, Body, HirId, Path, PathSegment};
+use rustc_hir::{Block, Body, HirId, Path, PathSegment, StabilityLevel, StableSince};
 use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::kw;
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 1cda6f596f4..490e6c974ae 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -13,8 +13,6 @@ use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
 
-use std::ops::ControlFlow;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for string appends of the form `x = x + y` (without
@@ -413,125 +411,6 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// This lint checks for `.to_string()` method calls on values of type `String`.
-    ///
-    /// ### Why restrict this?
-    /// The `to_string` method is also used on other types to convert them to a string.
-    /// When called on a `String` it only clones the `String`, which can be more specifically
-    /// expressed with `.clone()`.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// let msg = String::from("Hello World");
-    /// let _ = msg.to_string();
-    /// ```
-    /// Use instead:
-    /// ```no_run
-    /// let msg = String::from("Hello World");
-    /// let _ = msg.clone();
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub STRING_TO_STRING,
-    restriction,
-    "using `to_string()` on a `String`, which should be `clone()`"
-}
-
-declare_lint_pass!(StringToString => [STRING_TO_STRING]);
-
-fn is_parent_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<rustc_span::Span> {
-    if let Some(parent_expr) = get_parent_expr(cx, expr)
-        && let ExprKind::MethodCall(name, _, _, parent_span) = parent_expr.kind
-        && name.ident.name == sym::map
-        && let Some(caller_def_id) = cx.typeck_results().type_dependent_def_id(parent_expr.hir_id)
-        && (clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Result)
-            || clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Option)
-            || clippy_utils::is_diag_trait_item(cx, caller_def_id, sym::Iterator))
-    {
-        Some(parent_span)
-    } else {
-        None
-    }
-}
-
-fn is_called_from_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<rustc_span::Span> {
-    // Look for a closure as parent of `expr`, discarding simple blocks
-    let parent_closure = cx
-        .tcx
-        .hir_parent_iter(expr.hir_id)
-        .try_fold(expr.hir_id, |child_hir_id, (_, node)| match node {
-            // Check that the child expression is the only expression in the block
-            Node::Block(block) if block.stmts.is_empty() && block.expr.map(|e| e.hir_id) == Some(child_hir_id) => {
-                ControlFlow::Continue(block.hir_id)
-            },
-            Node::Expr(expr) if matches!(expr.kind, ExprKind::Block(..)) => ControlFlow::Continue(expr.hir_id),
-            Node::Expr(expr) if matches!(expr.kind, ExprKind::Closure(_)) => ControlFlow::Break(Some(expr)),
-            _ => ControlFlow::Break(None),
-        })
-        .break_value()?;
-    is_parent_map_like(cx, parent_closure?)
-}
-
-fn suggest_cloned_string_to_string(cx: &LateContext<'_>, span: rustc_span::Span) {
-    span_lint_and_sugg(
-        cx,
-        STRING_TO_STRING,
-        span,
-        "`to_string()` called on a `String`",
-        "try",
-        "cloned()".to_string(),
-        Applicability::MachineApplicable,
-    );
-}
-
-impl<'tcx> LateLintPass<'tcx> for StringToString {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-        if expr.span.from_expansion() {
-            return;
-        }
-
-        match &expr.kind {
-            ExprKind::MethodCall(path, self_arg, [], _) => {
-                if path.ident.name == sym::to_string
-                    && let ty = cx.typeck_results().expr_ty(self_arg)
-                    && is_type_lang_item(cx, ty.peel_refs(), LangItem::String)
-                {
-                    if let Some(parent_span) = is_called_from_map_like(cx, expr) {
-                        suggest_cloned_string_to_string(cx, parent_span);
-                    } else {
-                        #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
-                        span_lint_and_then(
-                            cx,
-                            STRING_TO_STRING,
-                            expr.span,
-                            "`to_string()` called on a `String`",
-                            |diag| {
-                                diag.help("consider using `.clone()`");
-                            },
-                        );
-                    }
-                }
-            },
-            ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
-                if segment.ident.name == sym::to_string
-                    && let rustc_hir::TyKind::Path(QPath::Resolved(_, path)) = ty.peel_refs().kind
-                    && let rustc_hir::def::Res::Def(_, def_id) = path.res
-                    && cx
-                        .tcx
-                        .lang_items()
-                        .get(LangItem::String)
-                        .is_some_and(|lang_id| lang_id == def_id)
-                    && let Some(parent_span) = is_parent_map_like(cx, expr)
-                {
-                    suggest_cloned_string_to_string(cx, parent_span);
-                }
-            },
-            _ => {},
-        }
-    }
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Warns about calling `str::trim` (or variants) before `str::split_whitespace`.
     ///
     /// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index 87f184e13ce..d5b6c175854 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -1,17 +1,20 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_context};
 use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source};
 use core::ops::ControlFlow;
+use rustc_ast::{FormatArgs, FormatArgumentKind};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{Visitor, walk_body};
+use rustc_hir::intravisit::{Visitor, walk_body, walk_expr};
 use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, LetStmt, MatchSource, Node, PatKind, QPath, TyKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
+use rustc_span::Span;
 
 use super::LET_UNIT_VALUE;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, format_args: &FormatArgsStorage, local: &'tcx LetStmt<'_>) {
     // skip `let () = { ... }`
     if let PatKind::Tuple(fields, ..) = local.pat.kind
         && fields.is_empty()
@@ -73,11 +76,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
                     let mut suggestions = Vec::new();
 
                     // Suggest omitting the `let` binding
-                    if let Some(expr) = &local.init {
-                        let mut app = Applicability::MachineApplicable;
-                        let snip = snippet_with_context(cx, expr.span, local.span.ctxt(), "()", &mut app).0;
-                        suggestions.push((local.span, format!("{snip};")));
-                    }
+                    let mut app = Applicability::MachineApplicable;
+                    let snip = snippet_with_context(cx, init.span, local.span.ctxt(), "()", &mut app).0;
 
                     // If this is a binding pattern, we need to add suggestions to remove any usages
                     // of the variable
@@ -85,53 +85,102 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
                         && let Some(body_id) = cx.enclosing_body.as_ref()
                     {
                         let body = cx.tcx.hir_body(*body_id);
-
-                        // Collect variable usages
-                        let mut visitor = UnitVariableCollector::new(binding_hir_id);
+                        let mut visitor = UnitVariableCollector::new(cx, format_args, binding_hir_id);
                         walk_body(&mut visitor, body);
 
-                        // Add suggestions for replacing variable usages
-                        suggestions.extend(visitor.spans.into_iter().map(|span| (span, "()".to_string())));
-                    }
+                        let mut has_in_format_capture = false;
+                        suggestions.extend(visitor.spans.iter().filter_map(|span| match span {
+                            MaybeInFormatCapture::Yes => {
+                                has_in_format_capture = true;
+                                None
+                            },
+                            MaybeInFormatCapture::No(span) => Some((*span, "()".to_string())),
+                        }));
 
-                    // Emit appropriate diagnostic based on whether there are usages of the let binding
-                    if !suggestions.is_empty() {
-                        let message = if suggestions.len() == 1 {
-                            "omit the `let` binding"
-                        } else {
-                            "omit the `let` binding and replace variable usages with `()`"
-                        };
-                        diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
+                        if has_in_format_capture {
+                            suggestions.push((
+                                init.span,
+                                format!("();\n{}", reindent_multiline(&snip, false, indent_of(cx, local.span))),
+                            ));
+                            diag.multipart_suggestion(
+                                "replace variable usages with `()`",
+                                suggestions,
+                                Applicability::MachineApplicable,
+                            );
+                            return;
+                        }
                     }
+
+                    suggestions.push((local.span, format!("{snip};")));
+                    let message = if suggestions.len() == 1 {
+                        "omit the `let` binding"
+                    } else {
+                        "omit the `let` binding and replace variable usages with `()`"
+                    };
+                    diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
                 },
             );
         }
     }
 }
 
-struct UnitVariableCollector {
+struct UnitVariableCollector<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    format_args: &'a FormatArgsStorage,
     id: HirId,
-    spans: Vec<rustc_span::Span>,
+    spans: Vec<MaybeInFormatCapture>,
+    macro_call: Option<&'a FormatArgs>,
 }
 
-impl UnitVariableCollector {
-    fn new(id: HirId) -> Self {
-        Self { id, spans: vec![] }
+enum MaybeInFormatCapture {
+    Yes,
+    No(Span),
+}
+
+impl<'a, 'tcx> UnitVariableCollector<'a, 'tcx> {
+    fn new(cx: &'a LateContext<'tcx>, format_args: &'a FormatArgsStorage, id: HirId) -> Self {
+        Self {
+            cx,
+            format_args,
+            id,
+            spans: Vec::new(),
+            macro_call: None,
+        }
     }
 }
 
 /**
  * Collect all instances where a variable is used based on its `HirId`.
  */
-impl<'tcx> Visitor<'tcx> for UnitVariableCollector {
+impl<'tcx> Visitor<'tcx> for UnitVariableCollector<'_, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
+        if let Some(macro_call) = root_macro_call_first_node(self.cx, ex)
+            && is_format_macro(self.cx, macro_call.def_id)
+            && let Some(format_args) = self.format_args.get(self.cx, ex, macro_call.expn)
+        {
+            let parent_macro_call = self.macro_call;
+            self.macro_call = Some(format_args);
+            walk_expr(self, ex);
+            self.macro_call = parent_macro_call;
+            return;
+        }
+
         if let ExprKind::Path(QPath::Resolved(None, path)) = ex.kind
             && let Res::Local(id) = path.res
             && id == self.id
         {
-            self.spans.push(path.span);
+            if let Some(macro_call) = self.macro_call
+                && macro_call.arguments.all_args().iter().any(|arg| {
+                    matches!(arg.kind, FormatArgumentKind::Captured(_)) && find_format_arg_expr(ex, arg).is_some()
+                })
+            {
+                self.spans.push(MaybeInFormatCapture::Yes);
+            } else {
+                self.spans.push(MaybeInFormatCapture::No(path.span));
+            }
         }
-        rustc_hir::intravisit::walk_expr(self, ex);
+
+        walk_expr(self, ex);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs
index e016bd3434b..4ffcc247acf 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs
@@ -3,9 +3,10 @@ mod unit_arg;
 mod unit_cmp;
 mod utils;
 
+use clippy_utils::macros::FormatArgsStorage;
 use rustc_hir::{Expr, LetStmt};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -96,11 +97,21 @@ declare_clippy_lint! {
     "passing unit to a function"
 }
 
-declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]);
+pub struct UnitTypes {
+    format_args: FormatArgsStorage,
+}
+
+impl_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]);
+
+impl UnitTypes {
+    pub fn new(format_args: FormatArgsStorage) -> Self {
+        Self { format_args }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for UnitTypes {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
-        let_unit_value::check(cx, local);
+        let_unit_value::check(cx, &self.format_args, local);
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 29931738412..2113cb92137 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -348,7 +348,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                             IntTy::I128 => "I128",
                         };
                         format!("LitIntType::Signed(IntTy::{t})")
-                    }
+                    },
                     LitIntType::Unsigned(uint_ty) => {
                         let t = match uint_ty {
                             UintTy::Usize => "Usize",
@@ -359,7 +359,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                             UintTy::U128 => "U128",
                         };
                         format!("LitIntType::Unsigned(UintTy::{t})")
-                    }
+                    },
                     LitIntType::Unsuffixed => String::from("LitIntType::Unsuffixed"),
                 };
                 kind!("Int({i}, {int_ty})");
@@ -374,7 +374,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                             FloatTy::F128 => "F128",
                         };
                         format!("LitFloatType::Suffixed(FloatTy::{t})")
-                    }
+                    },
                     LitFloatType::Unsuffixed => String::from("LitFloatType::Unsuffixed"),
                 };
                 kind!("Float(_, {float_ty})");
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 22fd15d153a..a2523b5fb07 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -118,7 +118,7 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
 
 impl LateLintPass<'_> for WildcardImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if cx.sess().is_test_crate() {
+        if cx.sess().is_test_crate() || item.span.in_external_macro(cx.sess().source_map()) {
             return;
         }
 
diff --git a/src/tools/clippy/clippy_lints_internal/src/derive_deserialize_allowing_unknown.rs b/src/tools/clippy/clippy_lints_internal/src/derive_deserialize_allowing_unknown.rs
index e0ae0c11cc2..5e6a40ac2eb 100644
--- a/src/tools/clippy/clippy_lints_internal/src/derive_deserialize_allowing_unknown.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/derive_deserialize_allowing_unknown.rs
@@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::paths;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::{AttrStyle, DelimArgs};
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{
-    AttrArgs, AttrItem, AttrPath, Attribute, HirId, Impl, Item, ItemKind, Path, QPath, TraitRef, Ty, TyKind,
+    AttrArgs, AttrItem, AttrPath, Attribute, HirId, Impl, Item, ItemKind, Path, QPath, TraitRef, Ty, TyKind, find_attr,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_lint_defs::declare_tool_lint;
diff --git a/src/tools/clippy/clippy_test_deps/Cargo.lock b/src/tools/clippy/clippy_test_deps/Cargo.lock
index 5be404f24e6..2f987c0137c 100644
--- a/src/tools/clippy/clippy_test_deps/Cargo.lock
+++ b/src/tools/clippy/clippy_test_deps/Cargo.lock
@@ -70,7 +70,6 @@ name = "clippy_test_deps"
 version = "0.1.0"
 dependencies = [
  "futures",
- "if_chain",
  "itertools",
  "libc",
  "parking_lot",
@@ -183,12 +182,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
-name = "if_chain"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
-
-[[package]]
 name = "io-uring"
 version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/clippy/clippy_test_deps/Cargo.toml b/src/tools/clippy/clippy_test_deps/Cargo.toml
index fcedc5d4843..e449b48bc46 100644
--- a/src/tools/clippy/clippy_test_deps/Cargo.toml
+++ b/src/tools/clippy/clippy_test_deps/Cargo.toml
@@ -9,7 +9,6 @@ edition = "2021"
 libc = "0.2"
 regex = "1.5.5"
 serde = { version = "1.0.145", features = ["derive"] }
-if_chain = "1.0"
 quote = "1.0.25"
 syn = { version = "2.0", features = ["full"] }
 futures = "0.3"
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 73291aa8cdf..bdf7431f29f 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.90"
+version = "0.1.91"
 edition = "2024"
 description = "Helpful tools for writing lints, provided as they are used in Clippy"
 repository = "https://github.com/rust-lang/rust-clippy"
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index 19e71f6af1d..6d8dd92d55d 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-07-25
+nightly-2025-08-07
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index 4ccd9c5300b..2d42e76dcbc 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -2,9 +2,9 @@ use crate::source::SpanRangeExt;
 use crate::{sym, tokenize_with_text};
 use rustc_ast::attr;
 use rustc_ast::attr::AttributeExt;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_errors::Applicability;
+use rustc_hir::attrs::AttributeKind;
+use rustc_hir::find_attr;
 use rustc_lexer::TokenKind;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{AdtDef, TyCtxt};
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 5b9b0ef3001..fc716d86fc6 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -83,19 +83,18 @@ pub use self::hir_utils::{
 use core::mem;
 use core::ops::ControlFlow;
 use std::collections::hash_map::Entry;
-use std::iter::{once, repeat_n};
+use std::iter::{once, repeat_n, zip};
 use std::sync::{Mutex, MutexGuard, OnceLock};
 
 use itertools::Itertools;
 use rustc_abi::Integer;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_ast::join_path_syms;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnindexMap;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::definitions::{DefPath, DefPathData};
@@ -106,7 +105,7 @@ use rustc_hir::{
     CoroutineKind, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, Impl,
     ImplItem, ImplItemKind, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
     Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem,
-    TraitItemKind, TraitRef, TyKind, UnOp, def,
+    TraitItemKind, TraitRef, TyKind, UnOp, def, find_attr,
 };
 use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -582,7 +581,7 @@ pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -
         return false;
     }
 
-    for (x1, x2) in s1.iter().zip(s2.iter()) {
+    for (x1, x2) in zip(&s1, &s2) {
         if expr_custom_deref_adjustment(cx, x1).is_some() || expr_custom_deref_adjustment(cx, x2).is_some() {
             return false;
         }
@@ -1898,42 +1897,11 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 /// * `|x| { return x; }`
 /// * `|(x, y)| (x, y)`
 /// * `|[x, y]| [x, y]`
+/// * `|Foo(bar, baz)| Foo(bar, baz)`
+/// * `|Foo { bar, baz }| Foo { bar, baz }`
 ///
 /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
 fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
-    fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
-        if cx
-            .typeck_results()
-            .pat_binding_modes()
-            .get(pat.hir_id)
-            .is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
-        {
-            // If the parameter is `(x, y)` of type `&(T, T)`, or `[x, y]` of type `&[T; 2]`, then
-            // due to match ergonomics, the inner patterns become references. Don't consider this
-            // the identity function as that changes types.
-            return false;
-        }
-
-        match (pat.kind, expr.kind) {
-            (PatKind::Binding(_, id, _, _), _) => {
-                path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty()
-            },
-            (PatKind::Tuple(pats, dotdot), ExprKind::Tup(tup))
-                if dotdot.as_opt_usize().is_none() && pats.len() == tup.len() =>
-            {
-                pats.iter().zip(tup).all(|(pat, expr)| check_pat(cx, pat, expr))
-            },
-            (PatKind::Slice(before, slice, after), ExprKind::Array(arr))
-                if slice.is_none() && before.len() + after.len() == arr.len() =>
-            {
-                (before.iter().chain(after))
-                    .zip(arr)
-                    .all(|(pat, expr)| check_pat(cx, pat, expr))
-            },
-            _ => false,
-        }
-    }
-
     let [param] = func.params else {
         return false;
     };
@@ -1966,11 +1934,81 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
                     return false;
                 }
             },
-            _ => return check_pat(cx, param.pat, expr),
+            _ => return is_expr_identity_of_pat(cx, param.pat, expr, true),
         }
     }
 }
 
+/// Checks if the given expression is an identity representation of the given pattern:
+/// * `x` is the identity representation of `x`
+/// * `(x, y)` is the identity representation of `(x, y)`
+/// * `[x, y]` is the identity representation of `[x, y]`
+/// * `Foo(bar, baz)` is the identity representation of `Foo(bar, baz)`
+/// * `Foo { bar, baz }` is the identity representation of `Foo { bar, baz }`
+///
+/// Note that `by_hir` is used to determine bindings are checked by their `HirId` or by their name.
+/// This can be useful when checking patterns in `let` bindings or `match` arms.
+pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>, by_hir: bool) -> bool {
+    if cx
+        .typeck_results()
+        .pat_binding_modes()
+        .get(pat.hir_id)
+        .is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
+    {
+        // If the parameter is `(x, y)` of type `&(T, T)`, or `[x, y]` of type `&[T; 2]`, then
+        // due to match ergonomics, the inner patterns become references. Don't consider this
+        // the identity function as that changes types.
+        return false;
+    }
+
+    // NOTE: we're inside a (function) body, so this won't ICE
+    let qpath_res = |qpath, hir| cx.typeck_results().qpath_res(qpath, hir);
+
+    match (pat.kind, expr.kind) {
+        (PatKind::Binding(_, id, _, _), _) if by_hir => {
+            path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty()
+        },
+        (PatKind::Binding(_, _, ident, _), ExprKind::Path(QPath::Resolved(_, path))) => {
+            matches!(path.segments, [ segment] if segment.ident.name == ident.name)
+        },
+        (PatKind::Tuple(pats, dotdot), ExprKind::Tup(tup))
+            if dotdot.as_opt_usize().is_none() && pats.len() == tup.len() =>
+        {
+            zip(pats, tup).all(|(pat, expr)| is_expr_identity_of_pat(cx, pat, expr, by_hir))
+        },
+        (PatKind::Slice(before, None, after), ExprKind::Array(arr)) if before.len() + after.len() == arr.len() => {
+            zip(before.iter().chain(after), arr).all(|(pat, expr)| is_expr_identity_of_pat(cx, pat, expr, by_hir))
+        },
+        (PatKind::TupleStruct(pat_ident, field_pats, dotdot), ExprKind::Call(ident, fields))
+            if dotdot.as_opt_usize().is_none() && field_pats.len() == fields.len() =>
+        {
+            // check ident
+            if let ExprKind::Path(ident) = &ident.kind
+                && qpath_res(&pat_ident, pat.hir_id) == qpath_res(ident, expr.hir_id)
+                // check fields
+                && zip(field_pats, fields).all(|(pat, expr)| is_expr_identity_of_pat(cx, pat, expr,by_hir))
+            {
+                true
+            } else {
+                false
+            }
+        },
+        (PatKind::Struct(pat_ident, field_pats, false), ExprKind::Struct(ident, fields, hir::StructTailExpr::None))
+            if field_pats.len() == fields.len() =>
+        {
+            // check ident
+            qpath_res(&pat_ident, pat.hir_id) == qpath_res(ident, expr.hir_id)
+                // check fields
+                && field_pats.iter().all(|field_pat| {
+                    fields.iter().any(|field| {
+                        field_pat.ident == field.ident && is_expr_identity_of_pat(cx, field_pat.pat, field.expr, by_hir)
+                    })
+                })
+        },
+        _ => false,
+    }
+}
+
 /// This is the same as [`is_expr_identity_function`], but does not consider closures
 /// with type annotations for its bindings (or similar) as identity functions:
 /// * `|x: u8| x`
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 480e0687756..89a83e2c48f 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -1,8 +1,8 @@
 use crate::sym;
 use rustc_ast::Attribute;
 use rustc_ast::attr::AttributeExt;
-use rustc_hir::RustcVersion;
 use rustc_attr_parsing::parse_version;
+use rustc_hir::RustcVersion;
 use rustc_lint::LateContext;
 use rustc_session::Session;
 use rustc_span::Symbol;
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 79116eba971..68f0b5ea255 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -5,10 +5,10 @@
 
 use crate::msrvs::{self, Msrv};
 use hir::LangItem;
-use rustc_hir::{RustcVersion, StableSince};
 use rustc_const_eval::check_consts::ConstCx;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::{RustcVersion, StableSince};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::Obligation;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 7d21336be1c..e675291b6f3 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -342,11 +342,8 @@ impl SourceFileRange {
     /// Attempts to get the text from the source file. This can fail if the source text isn't
     /// loaded.
     pub fn as_str(&self) -> Option<&str> {
-        self.sf
-            .src
-            .as_ref()
-            .map(|src| src.as_str())
-            .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source()))
+        (self.sf.src.as_ref().map(|src| src.as_str()))
+            .or_else(|| self.sf.external_src.get()?.get_source())
             .and_then(|x| x.get(self.range.clone()))
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 7a24d07fa1d..a63333c9b48 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -4,11 +4,11 @@
 use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
 use crate::ty::expr_sig;
 use crate::{get_parent_expr_for_hir, higher};
-use rustc_ast::ast;
 use rustc_ast::util::parser::AssocOp;
+use rustc_ast::{UnOp, ast};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
+use rustc_hir::{self as hir, Closure, ExprKind, HirId, MutTy, Node, TyKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::{EarlyContext, LateContext, LintContext};
 use rustc_middle::hir::place::ProjectionKind;
@@ -29,6 +29,11 @@ pub enum Sugg<'a> {
     /// A binary operator expression, including `as`-casts and explicit type
     /// coercion.
     BinOp(AssocOp, Cow<'a, str>, Cow<'a, str>),
+    /// A unary operator expression. This is used to sometimes represent `!`
+    /// or `-`, but only if the type with and without the operator is kept identical.
+    /// It means that doubling the operator can be used to remove it instead, in
+    /// order to provide better suggestions.
+    UnOp(UnOp, Box<Sugg<'a>>),
 }
 
 /// Literal constant `0`, for convenience.
@@ -40,9 +45,10 @@ pub const EMPTY: Sugg<'static> = Sugg::NonParen(Cow::Borrowed(""));
 
 impl Display for Sugg<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        match *self {
-            Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) => s.fmt(f),
-            Sugg::BinOp(op, ref lhs, ref rhs) => binop_to_string(op, lhs, rhs).fmt(f),
+        match self {
+            Sugg::NonParen(s) | Sugg::MaybeParen(s) => s.fmt(f),
+            Sugg::BinOp(op, lhs, rhs) => binop_to_string(*op, lhs, rhs).fmt(f),
+            Sugg::UnOp(op, inner) => write!(f, "{}{}", op.as_str(), inner.clone().maybe_inner_paren()),
         }
     }
 }
@@ -100,9 +106,19 @@ impl<'a> Sugg<'a> {
         applicability: &mut Applicability,
     ) -> Self {
         if expr.span.ctxt() == ctxt {
-            Self::hir_from_snippet(expr, |span| {
-                snippet_with_context(cx, span, ctxt, default, applicability).0
-            })
+            if let ExprKind::Unary(op, inner) = expr.kind
+                && matches!(op, UnOp::Neg | UnOp::Not)
+                && cx.typeck_results().expr_ty(expr) == cx.typeck_results().expr_ty(inner)
+            {
+                Sugg::UnOp(
+                    op,
+                    Box::new(Self::hir_with_context(cx, inner, ctxt, default, applicability)),
+                )
+            } else {
+                Self::hir_from_snippet(expr, |span| {
+                    snippet_with_context(cx, span, ctxt, default, applicability).0
+                })
+            }
         } else {
             let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
             Sugg::NonParen(snip)
@@ -341,6 +357,7 @@ impl<'a> Sugg<'a> {
                 let sugg = binop_to_string(op, &lhs, &rhs);
                 Sugg::NonParen(format!("({sugg})").into())
             },
+            Sugg::UnOp(op, inner) => Sugg::NonParen(format!("({}{})", op.as_str(), inner.maybe_inner_paren()).into()),
         }
     }
 
@@ -348,6 +365,26 @@ impl<'a> Sugg<'a> {
         match self {
             Sugg::NonParen(p) | Sugg::MaybeParen(p) => p.into_owned(),
             Sugg::BinOp(b, l, r) => binop_to_string(b, &l, &r),
+            Sugg::UnOp(op, inner) => format!("{}{}", op.as_str(), inner.maybe_inner_paren()),
+        }
+    }
+
+    /// Checks if `self` starts with a unary operator.
+    fn starts_with_unary_op(&self) -> bool {
+        match self {
+            Sugg::UnOp(..) => true,
+            Sugg::BinOp(..) => false,
+            Sugg::MaybeParen(s) | Sugg::NonParen(s) => s.starts_with(['*', '!', '-', '&']),
+        }
+    }
+
+    /// Call `maybe_paren` on `self` if it doesn't start with a unary operator,
+    /// don't touch it otherwise.
+    fn maybe_inner_paren(self) -> Self {
+        if self.starts_with_unary_op() {
+            self
+        } else {
+            self.maybe_paren()
         }
     }
 }
@@ -430,10 +467,11 @@ impl Sub for &Sugg<'_> {
 forward_binop_impls_to_ref!(impl Add, add for Sugg<'_>, type Output = Sugg<'static>);
 forward_binop_impls_to_ref!(impl Sub, sub for Sugg<'_>, type Output = Sugg<'static>);
 
-impl Neg for Sugg<'_> {
-    type Output = Sugg<'static>;
-    fn neg(self) -> Sugg<'static> {
-        match &self {
+impl<'a> Neg for Sugg<'a> {
+    type Output = Sugg<'a>;
+    fn neg(self) -> Self::Output {
+        match self {
+            Self::UnOp(UnOp::Neg, sugg) => *sugg,
             Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()),
             _ => make_unop("-", self),
         }
@@ -446,19 +484,21 @@ impl<'a> Not for Sugg<'a> {
         use AssocOp::Binary;
         use ast::BinOpKind::{Eq, Ge, Gt, Le, Lt, Ne};
 
-        if let Sugg::BinOp(op, lhs, rhs) = self {
-            let to_op = match op {
-                Binary(Eq) => Binary(Ne),
-                Binary(Ne) => Binary(Eq),
-                Binary(Lt) => Binary(Ge),
-                Binary(Ge) => Binary(Lt),
-                Binary(Gt) => Binary(Le),
-                Binary(Le) => Binary(Gt),
-                _ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
-            };
-            Sugg::BinOp(to_op, lhs, rhs)
-        } else {
-            make_unop("!", self)
+        match self {
+            Sugg::BinOp(op, lhs, rhs) => {
+                let to_op = match op {
+                    Binary(Eq) => Binary(Ne),
+                    Binary(Ne) => Binary(Eq),
+                    Binary(Lt) => Binary(Ge),
+                    Binary(Ge) => Binary(Lt),
+                    Binary(Gt) => Binary(Le),
+                    Binary(Le) => Binary(Gt),
+                    _ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
+                };
+                Sugg::BinOp(to_op, lhs, rhs)
+            },
+            Sugg::UnOp(UnOp::Not, expr) => *expr,
+            _ => make_unop("!", self),
         }
     }
 }
@@ -491,20 +531,11 @@ impl<T: Display> Display for ParenHelper<T> {
 /// Builds the string for `<op><expr>` adding parenthesis when necessary.
 ///
 /// For convenience, the operator is taken as a string because all unary
-/// operators have the same
-/// precedence.
+/// operators have the same precedence.
 pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
-    // If the `expr` starts with `op` already, do not add wrap it in
+    // If the `expr` starts with a unary operator already, do not wrap it in
     // parentheses.
-    let expr = if let Sugg::MaybeParen(ref sugg) = expr
-        && !has_enclosing_paren(sugg)
-        && sugg.starts_with(op)
-    {
-        expr
-    } else {
-        expr.maybe_paren()
-    };
-    Sugg::MaybeParen(format!("{op}{expr}").into())
+    Sugg::MaybeParen(format!("{op}{}", expr.maybe_inner_paren()).into())
 }
 
 /// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@@ -753,8 +784,10 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
         let mut visitor = DerefDelegate {
             cx,
             closure_span: closure.span,
+            closure_arg_id: closure_body.params[0].pat.hir_id,
             closure_arg_is_type_annotated_double_ref,
             next_pos: closure.span.lo(),
+            checked_borrows: FxHashSet::default(),
             suggestion_start: String::new(),
             applicability: Applicability::MachineApplicable,
         };
@@ -780,10 +813,15 @@ struct DerefDelegate<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     /// The span of the input closure to adapt
     closure_span: Span,
+    /// The `hir_id` of the closure argument being checked
+    closure_arg_id: HirId,
     /// Indicates if the arg of the closure is a type annotated double reference
     closure_arg_is_type_annotated_double_ref: bool,
     /// last position of the span to gradually build the suggestion
     next_pos: BytePos,
+    /// `hir_id`s that has been checked. This is used to avoid checking the same `hir_id` multiple
+    /// times when inside macro expansions.
+    checked_borrows: FxHashSet<HirId>,
     /// starting part of the gradually built suggestion
     suggestion_start: String,
     /// confidence on the built suggestion
@@ -847,9 +885,15 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
 
     fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
+    #[expect(clippy::too_many_lines)]
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
         if let PlaceBase::Local(id) = cmt.place.base {
             let span = self.cx.tcx.hir_span(cmt.hir_id);
+            if !self.checked_borrows.insert(cmt.hir_id) {
+                // already checked this span and hir_id, skip
+                return;
+            }
+
             let start_span = Span::new(self.next_pos, span.lo(), span.ctxt(), None);
             let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
 
@@ -858,7 +902,12 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
             // full identifier that includes projection (i.e.: `fp.field`)
             let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
 
-            if cmt.place.projections.is_empty() {
+            // Make sure to get in all projections if we're on a `matches!`
+            if let Node::Pat(pat) = self.cx.tcx.hir_node(id)
+                && pat.hir_id != self.closure_arg_id
+            {
+                let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
+            } else if cmt.place.projections.is_empty() {
                 // handle item without any projection, that needs an explicit borrowing
                 // i.e.: suggest `&x` instead of `x`
                 let _: fmt::Result = write!(self.suggestion_start, "{start_snip}&{ident_str}");
diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs
index 934be97d94e..ce7cc9348fb 100644
--- a/src/tools/clippy/clippy_utils/src/sym.rs
+++ b/src/tools/clippy/clippy_utils/src/sym.rs
@@ -171,7 +171,6 @@ generate! {
     has_significant_drop,
     hidden_glob_reexports,
     hygiene,
-    if_chain,
     insert,
     inspect,
     int_roundings,
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index 02a8eda5893..d79773f8321 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -6,13 +6,12 @@ use core::ops::ControlFlow;
 use itertools::Itertools;
 use rustc_abi::VariantIdx;
 use rustc_ast::ast::Mutability;
-use rustc_hir::attrs::{AttributeKind};
-use rustc_hir::find_attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Expr, FnDecl, LangItem, TyKind};
+use rustc_hir::{Expr, FnDecl, LangItem, TyKind, find_attr};
 use rustc_hir_analysis::lower_ty;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
@@ -583,7 +582,7 @@ pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(t
 }
 
 /// A signature for a function like type.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum ExprFnSig<'tcx> {
     Sig(Binder<'tcx, FnSig<'tcx>>, Option<DefId>),
     Closure(Option<&'tcx FnDecl<'tcx>>, Binder<'tcx, FnSig<'tcx>>),
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index bd6b4dfdee4..ec0e59e7054 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.90"
+version = "0.1.91"
 edition = "2024"
 repository = "https://github.com/rust-lang/rust-clippy"
 license = "MIT OR Apache-2.0"
diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs
index 408a2e087af..1ed059d2fb1 100644
--- a/src/tools/clippy/lintcheck/src/input.rs
+++ b/src/tools/clippy/lintcheck/src/input.rs
@@ -117,7 +117,7 @@ pub fn read_crates(toml_path: &Path) -> (Vec<CrateWithSource>, RecursiveOptions)
             crate_sources.push(CrateWithSource {
                 name: tk.name.clone(),
                 source: CrateSource::CratesIo {
-                    version: version.to_string(),
+                    version: version.clone(),
                 },
                 file_link: tk.file_link(DEFAULT_DOCS_LINK),
                 options: tk.options.clone(),
diff --git a/src/tools/clippy/lintcheck/src/json.rs b/src/tools/clippy/lintcheck/src/json.rs
index 808997ff022..79c1255c5ff 100644
--- a/src/tools/clippy/lintcheck/src/json.rs
+++ b/src/tools/clippy/lintcheck/src/json.rs
@@ -66,7 +66,7 @@ impl fmt::Display for Summary {
         } in &self.0
         {
             let html_id = to_html_id(name);
-            writeln!(f, "| [`{name}`](#{html_id}) | {added} | {changed} | {removed} |")?;
+            writeln!(f, "| [`{name}`](#{html_id}) | {added} | {removed} | {changed} |")?;
         }
 
         Ok(())
diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs
index d7fe0915121..1ecc3f7c249 100644
--- a/src/tools/clippy/lintcheck/src/output.rs
+++ b/src/tools/clippy/lintcheck/src/output.rs
@@ -220,7 +220,7 @@ fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, us
     let same_in_both_hashmaps = old_stats
         .iter()
         .filter(|(old_key, old_val)| new_stats.get::<&String>(old_key) == Some(old_val))
-        .map(|(k, v)| (k.to_string(), *v))
+        .map(|(k, v)| (k.clone(), *v))
         .collect::<Vec<(String, usize)>>();
 
     let mut old_stats_deduped = old_stats;
diff --git a/src/tools/clippy/rust-toolchain.toml b/src/tools/clippy/rust-toolchain.toml
index 0edb80edd04..ac51ec2d61b 100644
--- a/src/tools/clippy/rust-toolchain.toml
+++ b/src/tools/clippy/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-07-25"
+channel = "nightly-2025-08-07"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 464efc45c6b..6b6dfd7b81e 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -73,8 +73,7 @@ fn internal_extern_flags() -> Vec<String> {
             && INTERNAL_TEST_DEPENDENCIES.contains(&name)
         {
             // A dependency may be listed twice if it is available in sysroot,
-            // and the sysroot dependencies are listed first. As of the writing,
-            // this only seems to apply to if_chain.
+            // and the sysroot dependencies are listed first.
             crates.insert(name, path);
         }
     }
@@ -434,6 +433,7 @@ fn ui_cargo_toml_metadata() {
 #[derive(Template)]
 #[template(path = "index_template.html")]
 struct Renderer<'a> {
+    count: usize,
     lints: &'a Vec<LintMetadata>,
 }
 
@@ -513,7 +513,12 @@ impl DiagnosticCollector {
 
             fs::write(
                 "util/gh-pages/index.html",
-                Renderer { lints: &metadata }.render().unwrap(),
+                Renderer {
+                    count: LINTS.len(),
+                    lints: &metadata,
+                }
+                .render()
+                .unwrap(),
             )
             .unwrap();
         });
diff --git a/src/tools/clippy/tests/symbols-used.rs b/src/tools/clippy/tests/symbols-used.rs
index bc0456711fb..a1049ba64d5 100644
--- a/src/tools/clippy/tests/symbols-used.rs
+++ b/src/tools/clippy/tests/symbols-used.rs
@@ -75,7 +75,7 @@ fn all_symbols_are_used() -> Result<()> {
         for sym in extra {
             eprintln!("  - {sym}");
         }
-        Err(format!("extra symbols found — remove them {SYM_FILE}"))?;
+        Err(format!("extra symbols found — remove them from {SYM_FILE}"))?;
     }
     Ok(())
 }
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr
index 14a6b5047b1..666b842bf80 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr
@@ -7,7 +7,7 @@ error: unnecessary structure name repetition
 note: the lint level is defined here
   --> src/main.rs:6:9
    |
-6  | #![deny(clippy::use_self)]
+ 6 | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unnecessary structure name repetition
diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
index b626551e35b..8db52c47ad5 100644
--- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
+++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
@@ -14,10 +14,10 @@ error: file is loaded as a module multiple times: `src/b.rs`
 error: file is loaded as a module multiple times: `src/c.rs`
   --> src/main.rs:7:1
    |
-7  |   mod c;
+ 7 |   mod c;
    |   ^^^^^^ first loaded here
-8  | / #[path = "c.rs"]
-9  | | mod c2;
+ 8 | / #[path = "c.rs"]
+ 9 | | mod c2;
    | |_______^ loaded again here
 10 | / #[path = "c.rs"]
 11 | | mod c3;
@@ -44,8 +44,8 @@ error: file is loaded as a module multiple times: `src/from_other_module.rs`
    |
   ::: src/other_module/mod.rs:1:1
    |
-1  | / #[path = "../from_other_module.rs"]
-2  | | mod m;
+ 1 | / #[path = "../from_other_module.rs"]
+ 2 | | mod m;
    | |______^ loaded again here
    |
    = help: replace all but one `mod` item with `use` items
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
index 059427d8ee0..a87339a9a30 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
@@ -1,7 +1,7 @@
 error: lint group `rust_2018_idioms` has the same priority (0) as a lint
   --> Cargo.toml:7:1
    |
-7  | rust_2018_idioms = "warn"
+ 7 | rust_2018_idioms = "warn"
    | ^^^^^^^^^^^^^^^^   ------ has an implicit priority of 0
 ...
 12 | unused_attributes = { level = "allow" }
@@ -11,8 +11,8 @@ error: lint group `rust_2018_idioms` has the same priority (0) as a lint
    = note: `#[deny(clippy::lint_groups_priority)]` on by default
 help: to have lints override the group set `rust_2018_idioms` to a lower priority
    |
-7  - rust_2018_idioms = "warn"
-7  + rust_2018_idioms = { level = "warn", priority = -1 }
+ 7 - rust_2018_idioms = "warn"
+ 7 + rust_2018_idioms = { level = "warn", priority = -1 }
    |
 
 error: lint group `unused` has the same priority (0) as a lint
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
index 20511cbed16..ec9fbcfd4a3 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
@@ -1,3 +1,4 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
 #![warn(clippy::wildcard_imports)]
 
 mod prelude {
@@ -13,6 +14,10 @@ mod my_crate {
     pub mod utils {
         pub fn my_util_fn() {}
     }
+
+    pub mod utils2 {
+        pub const SOME_CONST: u32 = 1;
+    }
 }
 
 pub use utils::{BAR, print};
@@ -22,6 +27,12 @@ use my_crate::utils::my_util_fn;
 use prelude::FOO;
 //~^ ERROR: usage of wildcard import
 
+proc_macros::external! {
+    use my_crate::utils2::*;
+
+    static SOME_STATIC: u32 = SOME_CONST;
+}
+
 fn main() {
     let _ = FOO;
     let _ = BAR;
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
index 8d05910f471..233ee19f89b 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
@@ -1,3 +1,4 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
 #![warn(clippy::wildcard_imports)]
 
 mod prelude {
@@ -13,6 +14,10 @@ mod my_crate {
     pub mod utils {
         pub fn my_util_fn() {}
     }
+
+    pub mod utils2 {
+        pub const SOME_CONST: u32 = 1;
+    }
 }
 
 pub use utils::*;
@@ -22,6 +27,12 @@ use my_crate::utils::*;
 use prelude::*;
 //~^ ERROR: usage of wildcard import
 
+proc_macros::external! {
+    use my_crate::utils2::*;
+
+    static SOME_STATIC: u32 = SOME_CONST;
+}
+
 fn main() {
     let _ = FOO;
     let _ = BAR;
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
index 5e624dd6c3c..5d37cb705f5 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
@@ -1,5 +1,5 @@
 error: usage of wildcard import
-  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:9
+  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:23:9
    |
 LL | pub use utils::*;
    |         ^^^^^^^^ help: try: `utils::{BAR, print}`
@@ -8,13 +8,13 @@ LL | pub use utils::*;
    = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]`
 
 error: usage of wildcard import
-  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:20:5
+  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:25:5
    |
 LL | use my_crate::utils::*;
    |     ^^^^^^^^^^^^^^^^^^ help: try: `my_crate::utils::my_util_fn`
 
 error: usage of wildcard import
-  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:22:5
+  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:27:5
    |
 LL | use prelude::*;
    |     ^^^^^^^^^^ help: try: `prelude::FOO`
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer_unfixable.rs b/src/tools/clippy/tests/ui/cast_lossless_integer_unfixable.rs
new file mode 100644
index 00000000000..db9cbbb5b66
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer_unfixable.rs
@@ -0,0 +1,17 @@
+//@check-pass
+#![warn(clippy::cast_lossless)]
+
+fn issue15348() {
+    macro_rules! zero {
+        ($int:ty) => {{
+            let data: [u8; 3] = [0, 0, 0];
+            data[0] as $int
+        }};
+    }
+
+    let _ = zero!(u8);
+    let _ = zero!(u16);
+    let _ = zero!(u32);
+    let _ = zero!(u64);
+    let _ = zero!(u128);
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.fixed b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
index fed75244c6f..3d709fe9b8e 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
@@ -104,3 +104,25 @@ fn issue14799() {
         }
     }
 }
+
+fn in_parens() {
+    let x = "hello";
+    let y = "world";
+
+    if x == "hello" {
+        print!("Hello ");
+    } else if y == "world" { println!("world") } else { println!("!") }
+    //~^^^ collapsible_else_if
+}
+
+fn in_brackets() {
+    let x = "hello";
+    let y = "world";
+
+    // There is no lint when the inner `if` is in a block.
+    if x == "hello" {
+        print!("Hello ");
+    } else {
+        { if y == "world" { println!("world") } else { println!("!") } }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.rs b/src/tools/clippy/tests/ui/collapsible_else_if.rs
index e50e781fb69..51868e03908 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.rs
@@ -120,3 +120,27 @@ fn issue14799() {
         }
     }
 }
+
+fn in_parens() {
+    let x = "hello";
+    let y = "world";
+
+    if x == "hello" {
+        print!("Hello ");
+    } else {
+        (if y == "world" { println!("world") } else { println!("!") })
+    }
+    //~^^^ collapsible_else_if
+}
+
+fn in_brackets() {
+    let x = "hello";
+    let y = "world";
+
+    // There is no lint when the inner `if` is in a block.
+    if x == "hello" {
+        print!("Hello ");
+    } else {
+        { if y == "world" { println!("world") } else { println!("!") } }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.stderr b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
index 7d80894cadb..1a7bcec7fd5 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
@@ -150,5 +150,14 @@ LL | |         if false {}
 LL | |     }
    | |_____^ help: collapse nested if block: `if false {}`
 
-error: aborting due to 8 previous errors
+error: this `else { if .. }` block can be collapsed
+  --> tests/ui/collapsible_else_if.rs:130:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         (if y == "world" { println!("world") } else { println!("!") })
+LL | |     }
+   | |_____^ help: collapse nested if block: `if y == "world" { println!("world") } else { println!("!") }`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index 77bc791ea8e..78354c2d7cf 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -163,3 +163,21 @@ fn issue14799() {
         if true {}
     };
 }
+
+fn in_parens() {
+    if true
+        && true {
+            println!("In parens, linted");
+        }
+    //~^^^^^ collapsible_if
+}
+
+fn in_brackets() {
+    if true {
+        {
+            if true {
+                println!("In brackets, not linted");
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index d30df157d5e..5d9afa10956 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -173,3 +173,22 @@ fn issue14799() {
         if true {}
     };
 }
+
+fn in_parens() {
+    if true {
+        (if true {
+            println!("In parens, linted");
+        })
+    }
+    //~^^^^^ collapsible_if
+}
+
+fn in_brackets() {
+    if true {
+        {
+            if true {
+                println!("In brackets, not linted");
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 32c6b019403..a685cc2e929 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -190,5 +190,23 @@ LL |         // This is a comment, do not collapse code to it
 LL ~     ; 3
    |
 
-error: aborting due to 11 previous errors
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if.rs:178:5
+   |
+LL | /     if true {
+LL | |         (if true {
+LL | |             println!("In parens, linted");
+LL | |         })
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if true
+LL ~         && true {
+LL |             println!("In parens, linted");
+LL ~         }
+   |
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index 6b69bdd29ce..9743a83fb93 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -12,6 +12,7 @@
 #![warn(clippy::regex_macro)] //~ ERROR: lint `clippy::regex_macro`
 #![warn(clippy::replace_consts)] //~ ERROR: lint `clippy::replace_consts`
 #![warn(clippy::should_assert_eq)] //~ ERROR: lint `clippy::should_assert_eq`
+#![warn(clippy::string_to_string)] //~ ERROR: lint `clippy::string_to_string`
 #![warn(clippy::unsafe_vector_initialization)] //~ ERROR: lint `clippy::unsafe_vector_initialization`
 #![warn(clippy::unstable_as_mut_slice)] //~ ERROR: lint `clippy::unstable_as_mut_slice`
 #![warn(clippy::unstable_as_slice)] //~ ERROR: lint `clippy::unstable_as_slice`
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index 07e59d33d60..cd225da611c 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -61,35 +61,41 @@ error: lint `clippy::should_assert_eq` has been removed: `assert!(a == b)` can n
 LL | #![warn(clippy::should_assert_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unsafe_vector_initialization` has been removed: the suggested alternative could be substantially slower
+error: lint `clippy::string_to_string` has been removed: `clippy:implicit_clone` covers those cases
   --> tests/ui/deprecated.rs:15:9
    |
+LL | #![warn(clippy::string_to_string)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: lint `clippy::unsafe_vector_initialization` has been removed: the suggested alternative could be substantially slower
+  --> tests/ui/deprecated.rs:16:9
+   |
 LL | #![warn(clippy::unsafe_vector_initialization)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` is now stable
-  --> tests/ui/deprecated.rs:16:9
+  --> tests/ui/deprecated.rs:17:9
    |
 LL | #![warn(clippy::unstable_as_mut_slice)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` is now stable
-  --> tests/ui/deprecated.rs:17:9
+  --> tests/ui/deprecated.rs:18:9
    |
 LL | #![warn(clippy::unstable_as_slice)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::unused_collect` has been removed: `Iterator::collect` is now marked as `#[must_use]`
-  --> tests/ui/deprecated.rs:18:9
+  --> tests/ui/deprecated.rs:19:9
    |
 LL | #![warn(clippy::unused_collect)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::wrong_pub_self_convention` has been removed: `clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config
-  --> tests/ui/deprecated.rs:19:9
+  --> tests/ui/deprecated.rs:20:9
    |
 LL | #![warn(clippy::wrong_pub_self_convention)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 15 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 8cf20d8b1a1..bbbd5973036 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -83,7 +83,7 @@ fn test_units() {
 /// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
 /// TensorFlow
 /// TrueType
-/// iOS macOS FreeBSD NetBSD OpenBSD
+/// iOS macOS FreeBSD NetBSD OpenBSD NixOS
 /// TeX LaTeX BibTeX BibLaTeX
 /// MinGW
 /// CamelCase (see also #2395)
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 5b6f2bd8330..1077d3580d3 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -83,7 +83,7 @@ fn test_units() {
 /// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
 /// TensorFlow
 /// TrueType
-/// iOS macOS FreeBSD NetBSD OpenBSD
+/// iOS macOS FreeBSD NetBSD OpenBSD NixOS
 /// TeX LaTeX BibTeX BibLaTeX
 /// MinGW
 /// CamelCase (see also #2395)
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.rs b/src/tools/clippy/tests/ui/duplicated_attributes.rs
index 3ca91d6f182..9a671499505 100644
--- a/src/tools/clippy/tests/ui/duplicated_attributes.rs
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_attr.rs
+#![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] //~ ERROR: duplicated attribute
 #![feature(rustc_attrs)]
-#![warn(clippy::duplicated_attributes)]
 #![cfg(any(unix, windows))]
 #![allow(dead_code)]
 #![allow(dead_code)] //~ ERROR: duplicated attribute
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.stderr b/src/tools/clippy/tests/ui/duplicated_attributes.stderr
index 0903617a8d1..922939d60dd 100644
--- a/src/tools/clippy/tests/ui/duplicated_attributes.stderr
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.stderr
@@ -1,4 +1,23 @@
 error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:2:40
+   |
+LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:2:9
+   |
+LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:2:40
+   |
+LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
+
+error: duplicated attribute
   --> tests/ui/duplicated_attributes.rs:6:10
    |
 LL | #![allow(dead_code)]
@@ -14,8 +33,6 @@ help: remove this attribute
    |
 LL | #![allow(dead_code)]
    |          ^^^^^^^^^
-   = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
 
 error: duplicated attribute
   --> tests/ui/duplicated_attributes.rs:14:9
@@ -34,5 +51,5 @@ help: remove this attribute
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
index 419cf2354f8..22386245ffe 100644
--- a/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
+++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
@@ -32,3 +32,17 @@ macro_rules! empty_struct {
 empty_struct!(FromMacro);
 
 fn main() {}
+
+mod issue15349 {
+    trait Bar<T> {}
+    impl<T> Bar<T> for [u8; 7] {}
+
+    struct Foo<const N: usize>;
+    //~^ empty_structs_with_brackets
+    impl<const N: usize> Foo<N>
+    where
+        [u8; N]: Bar<[(); N]>,
+    {
+        fn foo() {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
index 90c415c1220..5cb54b66134 100644
--- a/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
@@ -32,3 +32,17 @@ macro_rules! empty_struct {
 empty_struct!(FromMacro);
 
 fn main() {}
+
+mod issue15349 {
+    trait Bar<T> {}
+    impl<T> Bar<T> for [u8; 7] {}
+
+    struct Foo<const N: usize> {}
+    //~^ empty_structs_with_brackets
+    impl<const N: usize> Foo<N>
+    where
+        [u8; N]: Bar<[(); N]>,
+    {
+        fn foo() {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr b/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr
index 86ef43aa960..f662bb9423e 100644
--- a/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr
+++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr
@@ -16,5 +16,13 @@ LL | struct MyEmptyTupleStruct(); // should trigger lint
    |
    = help: remove the brackets
 
-error: aborting due to 2 previous errors
+error: found empty brackets on struct declaration
+  --> tests/ui/empty_structs_with_brackets.rs:40:31
+   |
+LL |     struct Foo<const N: usize> {}
+   |                               ^^^
+   |
+   = help: remove the brackets
+
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.rs b/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.rs
new file mode 100644
index 00000000000..19123cd206e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.rs
@@ -0,0 +1,6 @@
+//@no-rustfix
+#![warn(clippy::four_forward_slashes)]
+
+//~v four_forward_slashes
+//// nondoc comment with bare CR: '
'
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.stderr b/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.stderr
new file mode 100644
index 00000000000..64e70b97db9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/four_forward_slashes_bare_cr.stderr
@@ -0,0 +1,14 @@
+error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
+  --> tests/ui/four_forward_slashes_bare_cr.rs:5:1
+   |
+LL | / //// nondoc comment with bare CR: '␍'
+LL | | fn main() {}
+   | |_^
+   |
+   = help: make this a doc comment by removing one `/`
+   = note: bare CR characters are not allowed in doc comments
+   = note: `-D clippy::four-forward-slashes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::four_forward_slashes)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/implicit_clone.fixed b/src/tools/clippy/tests/ui/implicit_clone.fixed
index d60d1cb0ec0..267514c5f3d 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.fixed
+++ b/src/tools/clippy/tests/ui/implicit_clone.fixed
@@ -135,4 +135,10 @@ fn main() {
     }
     let no_clone = &NoClone;
     let _ = no_clone.to_owned();
+
+    let s = String::from("foo");
+    let _ = s.clone();
+    //~^ implicit_clone
+    let _ = s.clone();
+    //~^ implicit_clone
 }
diff --git a/src/tools/clippy/tests/ui/implicit_clone.rs b/src/tools/clippy/tests/ui/implicit_clone.rs
index b96828f28c8..fba954026e7 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.rs
+++ b/src/tools/clippy/tests/ui/implicit_clone.rs
@@ -135,4 +135,10 @@ fn main() {
     }
     let no_clone = &NoClone;
     let _ = no_clone.to_owned();
+
+    let s = String::from("foo");
+    let _ = s.to_owned();
+    //~^ implicit_clone
+    let _ = s.to_string();
+    //~^ implicit_clone
 }
diff --git a/src/tools/clippy/tests/ui/implicit_clone.stderr b/src/tools/clippy/tests/ui/implicit_clone.stderr
index 1eb6ff1fe42..4cca9b0d0c0 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.stderr
+++ b/src/tools/clippy/tests/ui/implicit_clone.stderr
@@ -67,5 +67,17 @@ error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenc
 LL |     let _ = pathbuf_ref.to_path_buf();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(**pathbuf_ref).clone()`
 
-error: aborting due to 11 previous errors
+error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
+  --> tests/ui/implicit_clone.rs:140:13
+   |
+LL |     let _ = s.to_owned();
+   |             ^^^^^^^^^^^^ help: consider using: `s.clone()`
+
+error: implicitly cloning a `String` by calling `to_string` on its dereferenced type
+  --> tests/ui/implicit_clone.rs:142:13
+   |
+LL |     let _ = s.to_string();
+   |             ^^^^^^^^^^^^^ help: consider using: `s.clone()`
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
index 72edc539f04..edf6f014d3d 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
@@ -1,8 +1,5 @@
 #![deny(clippy::index_refutable_slice)]
 
-extern crate if_chain;
-use if_chain::if_chain;
-
 macro_rules! if_let_slice_macro {
     () => {
         // This would normally be linted
@@ -18,12 +15,9 @@ fn main() {
     if_let_slice_macro!();
 
     // Do lint this
-    if_chain! {
-        let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-        if let Some([slice_0, ..]) = slice;
+    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
+    if let Some([slice_0, ..]) = slice {
         //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        then {
-            println!("{}", slice_0);
-        }
+        println!("{}", slice_0);
     }
 }
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
index 7b474ba423b..76d4a2350f5 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
@@ -1,8 +1,5 @@
 #![deny(clippy::index_refutable_slice)]
 
-extern crate if_chain;
-use if_chain::if_chain;
-
 macro_rules! if_let_slice_macro {
     () => {
         // This would normally be linted
@@ -18,12 +15,9 @@ fn main() {
     if_let_slice_macro!();
 
     // Do lint this
-    if_chain! {
-        let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-        if let Some(slice) = slice;
+    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
+    if let Some(slice) = slice {
         //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        then {
-            println!("{}", slice[0]);
-        }
+        println!("{}", slice[0]);
     }
 }
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
index 64741abb911..635e6d19aef 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
@@ -1,8 +1,8 @@
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:23:21
+  --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:19:17
    |
-LL |         if let Some(slice) = slice;
-   |                     ^^^^^
+LL |     if let Some(slice) = slice {
+   |                 ^^^^^
    |
 note: the lint level is defined here
   --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:1:9
@@ -11,10 +11,9 @@ LL | #![deny(clippy::index_refutable_slice)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: replace the binding and indexed access with a slice pattern
    |
-LL ~         if let Some([slice_0, ..]) = slice;
+LL ~     if let Some([slice_0, ..]) = slice {
 LL |
-LL |         then {
-LL ~             println!("{}", slice_0);
+LL ~         println!("{}", slice_0);
    |
 
 error: aborting due to 1 previous error
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
index cad77f56d03..dea31530a0b 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
@@ -1,6 +1,5 @@
 //@aux-build: proc_macros.rs
 
-#![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
 #![warn(clippy::out_of_bounds_indexing)]
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
index e3ef89823e3..e3d6086544d 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
@@ -1,5 +1,5 @@
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:115:6
+  --> tests/ui/indexing_slicing_slice.rs:114:6
    |
 LL |     &x[index..];
    |      ^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     &x[index..];
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:117:6
+  --> tests/ui/indexing_slicing_slice.rs:116:6
    |
 LL |     &x[..index];
    |      ^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     &x[..index];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:119:6
+  --> tests/ui/indexing_slicing_slice.rs:118:6
    |
 LL |     &x[index_from..index_to];
    |      ^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     &x[index_from..index_to];
    = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:121:6
+  --> tests/ui/indexing_slicing_slice.rs:120:6
    |
 LL |     &x[index_from..][..index_to];
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     &x[index_from..][..index_to];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:121:6
+  --> tests/ui/indexing_slicing_slice.rs:120:6
    |
 LL |     &x[index_from..][..index_to];
    |      ^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     &x[index_from..][..index_to];
    = help: consider using `.get(n..)` or .get_mut(n..)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:124:6
+  --> tests/ui/indexing_slicing_slice.rs:123:6
    |
 LL |     &x[5..][..10];
    |      ^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |     &x[5..][..10];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:124:8
+  --> tests/ui/indexing_slicing_slice.rs:123:8
    |
 LL |     &x[5..][..10];
    |        ^
@@ -58,7 +58,7 @@ LL |     &x[5..][..10];
    = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:127:6
+  --> tests/ui/indexing_slicing_slice.rs:126:6
    |
 LL |     &x[0..][..3];
    |      ^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     &x[0..][..3];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:129:6
+  --> tests/ui/indexing_slicing_slice.rs:128:6
    |
 LL |     &x[1..][..5];
    |      ^^^^^^^^^^^
@@ -74,19 +74,19 @@ LL |     &x[1..][..5];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:137:12
+  --> tests/ui/indexing_slicing_slice.rs:136:12
    |
 LL |     &y[0..=4];
    |            ^
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:139:11
+  --> tests/ui/indexing_slicing_slice.rs:138:11
    |
 LL |     &y[..=4];
    |           ^
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:145:6
+  --> tests/ui/indexing_slicing_slice.rs:144:6
    |
 LL |     &v[10..100];
    |      ^^^^^^^^^^
@@ -94,7 +94,7 @@ LL |     &v[10..100];
    = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:147:6
+  --> tests/ui/indexing_slicing_slice.rs:146:6
    |
 LL |     &x[10..][..100];
    |      ^^^^^^^^^^^^^^
@@ -102,13 +102,13 @@ LL |     &x[10..][..100];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:147:8
+  --> tests/ui/indexing_slicing_slice.rs:146:8
    |
 LL |     &x[10..][..100];
    |        ^^
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:150:6
+  --> tests/ui/indexing_slicing_slice.rs:149:6
    |
 LL |     &v[10..];
    |      ^^^^^^^
@@ -116,7 +116,7 @@ LL |     &v[10..];
    = help: consider using `.get(n..)` or .get_mut(n..)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:152:6
+  --> tests/ui/indexing_slicing_slice.rs:151:6
    |
 LL |     &v[..100];
    |      ^^^^^^^^
@@ -124,7 +124,7 @@ LL |     &v[..100];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_slice.rs:170:5
+  --> tests/ui/indexing_slicing_slice.rs:169:5
    |
 LL |     map_with_get[true];
    |     ^^^^^^^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL |     map_with_get[true];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_slice.rs:174:5
+  --> tests/ui/indexing_slicing_slice.rs:173:5
    |
 LL |     s[0];
    |     ^^^^
@@ -140,7 +140,7 @@ LL |     s[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_slice.rs:178:5
+  --> tests/ui/indexing_slicing_slice.rs:177:5
    |
 LL |     y[0];
    |     ^^^^
diff --git a/src/tools/clippy/tests/ui/infallible_try_from.stderr b/src/tools/clippy/tests/ui/infallible_try_from.stderr
index 705b1188489..d1e0d9e7d3b 100644
--- a/src/tools/clippy/tests/ui/infallible_try_from.stderr
+++ b/src/tools/clippy/tests/ui/infallible_try_from.stderr
@@ -1,4 +1,4 @@
-error: infallible TryFrom impl; consider implementing From, instead
+error: infallible TryFrom impl; consider implementing From instead
   --> tests/ui/infallible_try_from.rs:8:1
    |
 LL | impl TryFrom<i8> for MyStruct {
@@ -10,7 +10,7 @@ LL |     type Error = !;
    = note: `-D clippy::infallible-try-from` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::infallible_try_from)]`
 
-error: infallible TryFrom impl; consider implementing From, instead
+error: infallible TryFrom impl; consider implementing From instead
   --> tests/ui/infallible_try_from.rs:16:1
    |
 LL | impl TryFrom<i16> for MyStruct {
diff --git a/src/tools/clippy/tests/ui/ip_constant.fixed b/src/tools/clippy/tests/ui/ip_constant.fixed
index 2e3389c1193..c9479682139 100644
--- a/src/tools/clippy/tests/ui/ip_constant.fixed
+++ b/src/tools/clippy/tests/ui/ip_constant.fixed
@@ -48,6 +48,20 @@ fn literal_test3() {
     //~^ ip_constant
 }
 
+fn wrapped_in_parens() {
+    let _ = std::net::Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    let _ = std::net::Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = std::net::Ipv6Addr::UNSPECIFIED;
+    //~^ ip_constant
+}
+
 const CONST_U8_0: u8 = 0;
 const CONST_U8_1: u8 = 1;
 const CONST_U8_127: u8 = 127;
diff --git a/src/tools/clippy/tests/ui/ip_constant.rs b/src/tools/clippy/tests/ui/ip_constant.rs
index 15e0b0551ba..69a5c3b4e92 100644
--- a/src/tools/clippy/tests/ui/ip_constant.rs
+++ b/src/tools/clippy/tests/ui/ip_constant.rs
@@ -48,6 +48,20 @@ fn literal_test3() {
     //~^ ip_constant
 }
 
+fn wrapped_in_parens() {
+    let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1));
+    //~^ ip_constant
+    let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255));
+    //~^ ip_constant
+    let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0));
+    //~^ ip_constant
+
+    let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    //~^ ip_constant
+    let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+    //~^ ip_constant
+}
+
 const CONST_U8_0: u8 = 0;
 const CONST_U8_1: u8 = 1;
 const CONST_U8_127: u8 = 127;
diff --git a/src/tools/clippy/tests/ui/ip_constant.stderr b/src/tools/clippy/tests/ui/ip_constant.stderr
index 3e984c6cb3b..07d912b18a5 100644
--- a/src/tools/clippy/tests/ui/ip_constant.stderr
+++ b/src/tools/clippy/tests/ui/ip_constant.stderr
@@ -181,8 +181,68 @@ LL +     let _ = std::net::Ipv6Addr::UNSPECIFIED;
    |
 
 error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:52:13
+   |
+LL |     let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1));
+LL +     let _ = std::net::Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:54:13
+   |
+LL |     let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255));
+LL +     let _ = std::net::Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:56:13
+   |
+LL |     let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0));
+LL +     let _ = std::net::Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:59:13
+   |
+LL |     let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+LL +     let _ = std::net::Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
   --> tests/ui/ip_constant.rs:61:13
    |
+LL |     let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+LL +     let _ = std::net::Ipv6Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:75:13
+   |
 LL |     let _ = Ipv4Addr::new(CONST_U8_127, CONST_U8_0, CONST_U8_0, CONST_U8_1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -193,7 +253,7 @@ LL +     let _ = Ipv4Addr::LOCALHOST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:63:13
+  --> tests/ui/ip_constant.rs:77:13
    |
 LL |     let _ = Ipv4Addr::new(CONST_U8_255, CONST_U8_255, CONST_U8_255, CONST_U8_255);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -205,7 +265,7 @@ LL +     let _ = Ipv4Addr::BROADCAST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:65:13
+  --> tests/ui/ip_constant.rs:79:13
    |
 LL |     let _ = Ipv4Addr::new(CONST_U8_0, CONST_U8_0, CONST_U8_0, CONST_U8_0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -217,7 +277,7 @@ LL +     let _ = Ipv4Addr::UNSPECIFIED;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:69:13
+  --> tests/ui/ip_constant.rs:83:13
    |
 LL |       let _ = Ipv6Addr::new(
    |  _____________^
@@ -246,7 +306,7 @@ LL +     let _ = Ipv6Addr::LOCALHOST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:81:13
+  --> tests/ui/ip_constant.rs:95:13
    |
 LL |       let _ = Ipv6Addr::new(
    |  _____________^
@@ -275,7 +335,7 @@ LL +     let _ = Ipv6Addr::UNSPECIFIED;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:96:13
+  --> tests/ui/ip_constant.rs:110:13
    |
 LL |     let _ = Ipv4Addr::new(126 + 1, 0, 0, 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +347,7 @@ LL +     let _ = Ipv4Addr::LOCALHOST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:98:13
+  --> tests/ui/ip_constant.rs:112:13
    |
 LL |     let _ = Ipv4Addr::new(254 + CONST_U8_1, 255, { 255 - CONST_U8_0 }, CONST_U8_255);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -299,7 +359,7 @@ LL +     let _ = Ipv4Addr::BROADCAST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:100:13
+  --> tests/ui/ip_constant.rs:114:13
    |
 LL |     let _ = Ipv4Addr::new(0, CONST_U8_255 - 255, 0, { 1 + 0 - 1 });
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -311,7 +371,7 @@ LL +     let _ = Ipv4Addr::UNSPECIFIED;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:104:13
+  --> tests/ui/ip_constant.rs:118:13
    |
 LL |     let _ = Ipv6Addr::new(0 + CONST_U16_0, 0, 0, 0, 0, 0, 0, 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -323,7 +383,7 @@ LL +     let _ = Ipv6Addr::LOCALHOST;
    |
 
 error: hand-coded well-known IP address
-  --> tests/ui/ip_constant.rs:106:13
+  --> tests/ui/ip_constant.rs:120:13
    |
 LL |     let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -334,5 +394,5 @@ LL -     let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1)
 LL +     let _ = Ipv6Addr::LOCALHOST;
    |
 
-error: aborting due to 25 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_on_single_items.fixed b/src/tools/clippy/tests/ui/iter_on_single_items.fixed
index b43fad6449c..044037aac2e 100644
--- a/src/tools/clippy/tests/ui/iter_on_single_items.fixed
+++ b/src/tools/clippy/tests/ui/iter_on_single_items.fixed
@@ -66,3 +66,27 @@ fn main() {
     custom_option::custom_option();
     in_macros!();
 }
+
+mod issue14981 {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    fn let_stmt() {
+        macro_rules! x {
+            ($e:expr) => {
+                let _: IntoIter<i32> = $e;
+            };
+        }
+        x!(Some(5).into_iter());
+    }
+
+    fn fn_ptr() {
+        fn some_func(_: IntoIter<i32>) -> IntoIter<i32> {
+            todo!()
+        }
+        some_func(Some(5).into_iter());
+
+        const C: fn(IntoIter<i32>) -> IntoIter<i32> = <IntoIter<i32> as IntoIterator>::into_iter;
+        C(Some(5).into_iter());
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_on_single_items.rs b/src/tools/clippy/tests/ui/iter_on_single_items.rs
index 625c96d3ef1..c925d0e480f 100644
--- a/src/tools/clippy/tests/ui/iter_on_single_items.rs
+++ b/src/tools/clippy/tests/ui/iter_on_single_items.rs
@@ -66,3 +66,27 @@ fn main() {
     custom_option::custom_option();
     in_macros!();
 }
+
+mod issue14981 {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    fn let_stmt() {
+        macro_rules! x {
+            ($e:expr) => {
+                let _: IntoIter<i32> = $e;
+            };
+        }
+        x!(Some(5).into_iter());
+    }
+
+    fn fn_ptr() {
+        fn some_func(_: IntoIter<i32>) -> IntoIter<i32> {
+            todo!()
+        }
+        some_func(Some(5).into_iter());
+
+        const C: fn(IntoIter<i32>) -> IntoIter<i32> = <IntoIter<i32> as IntoIterator>::into_iter;
+        C(Some(5).into_iter());
+    }
+}
diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed
index 304eacecd94..381d4cac462 100644
--- a/src/tools/clippy/tests/ui/let_unit.fixed
+++ b/src/tools/clippy/tests/ui/let_unit.fixed
@@ -198,3 +198,14 @@ pub fn issue12594() {
         returns_result(res).unwrap();
     }
 }
+
+fn issue15061() {
+    fn return_unit() {}
+    fn do_something(x: ()) {}
+
+    let res = ();
+    return_unit();
+    //~^ let_unit_value
+    do_something(());
+    println!("{res:?}");
+}
diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs
index a02cb346ff9..cdfc74991c4 100644
--- a/src/tools/clippy/tests/ui/let_unit.rs
+++ b/src/tools/clippy/tests/ui/let_unit.rs
@@ -198,3 +198,13 @@ pub fn issue12594() {
         returns_result(res).unwrap();
     }
 }
+
+fn issue15061() {
+    fn return_unit() {}
+    fn do_something(x: ()) {}
+
+    let res = return_unit();
+    //~^ let_unit_value
+    do_something(res);
+    println!("{res:?}");
+}
diff --git a/src/tools/clippy/tests/ui/let_unit.stderr b/src/tools/clippy/tests/ui/let_unit.stderr
index d743110c99d..637c9ff686b 100644
--- a/src/tools/clippy/tests/ui/let_unit.stderr
+++ b/src/tools/clippy/tests/ui/let_unit.stderr
@@ -68,5 +68,19 @@ LL ~         returns_result(()).unwrap();
 LL ~         returns_result(()).unwrap();
    |
 
-error: aborting due to 4 previous errors
+error: this let-binding has unit value
+  --> tests/ui/let_unit.rs:206:5
+   |
+LL |     let res = return_unit();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace variable usages with `()`
+   |
+LL ~     let res = ();
+LL ~     return_unit();
+LL |
+LL ~     do_something(());
+   |
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.fixed b/src/tools/clippy/tests/ui/let_with_type_underscore.fixed
index 7a4af4e3d1e..6339fe595c2 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.fixed
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.fixed
@@ -45,3 +45,15 @@ fn main() {
         x = ();
     };
 }
+
+fn issue15377() {
+    let (a) = 0;
+    //~^ let_with_type_underscore
+    let ((a)) = 0;
+    //~^ let_with_type_underscore
+    let ((a,)) = (0,);
+    //~^ let_with_type_underscore
+    #[rustfmt::skip]
+    let (   (a   )   ) = 0;
+    //~^ let_with_type_underscore
+}
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.rs b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
index a7c2f598b56..bd85346cf01 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.rs
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
@@ -45,3 +45,15 @@ fn main() {
         x = ();
     };
 }
+
+fn issue15377() {
+    let (a): _ = 0;
+    //~^ let_with_type_underscore
+    let ((a)): _ = 0;
+    //~^ let_with_type_underscore
+    let ((a,)): _ = (0,);
+    //~^ let_with_type_underscore
+    #[rustfmt::skip]
+    let (   (a   )   ):  _ = 0;
+    //~^ let_with_type_underscore
+}
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
index 9179f992207..c3f6c82397b 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
@@ -60,5 +60,53 @@ LL -     let x : _ = 1;
 LL +     let x = 1;
    |
 
-error: aborting due to 5 previous errors
+error: variable declared with type underscore
+  --> tests/ui/let_with_type_underscore.rs:50:5
+   |
+LL |     let (a): _ = 0;
+   |     ^^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+   |
+LL -     let (a): _ = 0;
+LL +     let (a) = 0;
+   |
+
+error: variable declared with type underscore
+  --> tests/ui/let_with_type_underscore.rs:52:5
+   |
+LL |     let ((a)): _ = 0;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+   |
+LL -     let ((a)): _ = 0;
+LL +     let ((a)) = 0;
+   |
+
+error: variable declared with type underscore
+  --> tests/ui/let_with_type_underscore.rs:54:5
+   |
+LL |     let ((a,)): _ = (0,);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+   |
+LL -     let ((a,)): _ = (0,);
+LL +     let ((a,)) = (0,);
+   |
+
+error: variable declared with type underscore
+  --> tests/ui/let_with_type_underscore.rs:57:5
+   |
+LL |     let (   (a   )   ):  _ = 0;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+   |
+LL -     let (   (a   )   ):  _ = 0;
+LL +     let (   (a   )   ) = 0;
+   |
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index 221cddf069d..2e9c9045caa 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -167,7 +167,7 @@ LL -         comment */
 LL -         /// Doc comment
 LL -         panic!("panic with comment") // comment after `panic!`
 LL -     }
-LL +     assert!(!(a > 2), "panic with comment");
+LL +     assert!(a <= 2, "panic with comment");
    |
 
 error: only a `panic!` in `if`-then statement
@@ -186,7 +186,7 @@ LL -         const BAR: () = if N == 0 {
 LL -
 LL -             panic!()
 LL -         };
-LL +         const BAR: () = assert!(!(N == 0), );
+LL +         const BAR: () = assert!(N != 0, );
    |
 
 error: only a `panic!` in `if`-then statement
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
index 221cddf069d..2e9c9045caa 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
@@ -167,7 +167,7 @@ LL -         comment */
 LL -         /// Doc comment
 LL -         panic!("panic with comment") // comment after `panic!`
 LL -     }
-LL +     assert!(!(a > 2), "panic with comment");
+LL +     assert!(a <= 2, "panic with comment");
    |
 
 error: only a `panic!` in `if`-then statement
@@ -186,7 +186,7 @@ LL -         const BAR: () = if N == 0 {
 LL -
 LL -             panic!()
 LL -         };
-LL +         const BAR: () = assert!(!(N == 0), );
+LL +         const BAR: () = assert!(N != 0, );
    |
 
 error: only a `panic!` in `if`-then statement
diff --git a/src/tools/clippy/tests/ui/manual_strip.rs b/src/tools/clippy/tests/ui/manual_strip.rs
index 086b75a3987..0fdaa1c045e 100644
--- a/src/tools/clippy/tests/ui/manual_strip.rs
+++ b/src/tools/clippy/tests/ui/manual_strip.rs
@@ -75,7 +75,7 @@ fn main() {
         s4[2..].to_string();
     }
 
-    // Don't propose to reuse the `stripped` identifier as it is overriden
+    // Don't propose to reuse the `stripped` identifier as it is overridden
     if s.starts_with("ab") {
         let stripped = &s["ab".len()..];
         //~^ ERROR: stripping a prefix manually
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
index 41ca44ceef4..189fe876aa5 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
@@ -102,7 +102,7 @@ fn issue_12928() {
     let y = if let Some(Y(a, ..)) = x { a } else { 0 };
 }
 
-// For symetry with `manual_unwrap_or` test
+// For symmetry with `manual_unwrap_or` test
 fn allowed_manual_unwrap_or_zero() -> u32 {
     Some(42).unwrap_or_default()
 }
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
index 343fbc4879c..ca87926763c 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
@@ -138,7 +138,7 @@ fn issue_12928() {
     let y = if let Some(Y(a, ..)) = x { a } else { 0 };
 }
 
-// For symetry with `manual_unwrap_or` test
+// For symmetry with `manual_unwrap_or` test
 fn allowed_manual_unwrap_or_zero() -> u32 {
     if let Some(x) = Some(42) {
         //~^ manual_unwrap_or_default
diff --git a/src/tools/clippy/tests/ui/map_identity.fixed b/src/tools/clippy/tests/ui/map_identity.fixed
index b82d3e6d956..6c971ba6338 100644
--- a/src/tools/clippy/tests/ui/map_identity.fixed
+++ b/src/tools/clippy/tests/ui/map_identity.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::map_identity)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::disallowed_names)]
 
 fn main() {
     let x: [u16; 3] = [1, 2, 3];
@@ -99,3 +99,65 @@ fn issue15198() {
     let _ = x.iter().copied();
     //~^ map_identity
 }
+
+mod foo {
+    #[derive(Clone, Copy)]
+    pub struct Foo {
+        pub foo: u8,
+        pub bar: u8,
+    }
+
+    #[derive(Clone, Copy)]
+    pub struct Foo2(pub u8, pub u8);
+}
+use foo::{Foo, Foo2};
+
+struct Bar {
+    foo: u8,
+    bar: u8,
+}
+
+struct Bar2(u8, u8);
+
+fn structs() {
+    let x = [Foo { foo: 0, bar: 0 }];
+
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar });
+
+    // still lint with redundant field names
+    #[allow(clippy::redundant_field_names)]
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint with field order change
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo });
+}
+
+fn tuple_structs() {
+    let x = [Foo2(0, 0)];
+
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter();
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar));
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo));
+}
diff --git a/src/tools/clippy/tests/ui/map_identity.rs b/src/tools/clippy/tests/ui/map_identity.rs
index c295bf87270..59dcfcda3b6 100644
--- a/src/tools/clippy/tests/ui/map_identity.rs
+++ b/src/tools/clippy/tests/ui/map_identity.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::map_identity)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::disallowed_names)]
 
 fn main() {
     let x: [u16; 3] = [1, 2, 3];
@@ -105,3 +105,65 @@ fn issue15198() {
     let _ = x.iter().copied().map(|[x, y]| [x, y]);
     //~^ map_identity
 }
+
+mod foo {
+    #[derive(Clone, Copy)]
+    pub struct Foo {
+        pub foo: u8,
+        pub bar: u8,
+    }
+
+    #[derive(Clone, Copy)]
+    pub struct Foo2(pub u8, pub u8);
+}
+use foo::{Foo, Foo2};
+
+struct Bar {
+    foo: u8,
+    bar: u8,
+}
+
+struct Bar2(u8, u8);
+
+fn structs() {
+    let x = [Foo { foo: 0, bar: 0 }];
+
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar });
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar });
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar });
+
+    // still lint with redundant field names
+    #[allow(clippy::redundant_field_names)]
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar });
+    //~^ map_identity
+
+    // still lint with field order change
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo });
+    //~^ map_identity
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo });
+}
+
+fn tuple_structs() {
+    let x = [Foo2(0, 0)];
+
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar));
+    //~^ map_identity
+
+    // still lint when different paths are used for the same struct
+    let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar));
+    //~^ map_identity
+
+    // don't lint: same fields but different structs
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar));
+
+    // don't lint: switched field assignment
+    let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo));
+}
diff --git a/src/tools/clippy/tests/ui/map_identity.stderr b/src/tools/clippy/tests/ui/map_identity.stderr
index 9b624a0dc75..a50c0d6b87b 100644
--- a/src/tools/clippy/tests/ui/map_identity.stderr
+++ b/src/tools/clippy/tests/ui/map_identity.stderr
@@ -93,5 +93,41 @@ error: unnecessary map of the identity function
 LL |     let _ = x.iter().copied().map(|[x, y]| [x, y]);
    |                              ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
 
-error: aborting due to 14 previous errors
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:131:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:135:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:143:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:147:26
+   |
+LL |     let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo });
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:157:26
+   |
+LL |     let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: unnecessary map of the identity function
+  --> tests/ui/map_identity.rs:161:26
+   |
+LL |     let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index e11dea35204..e29fb87dbc3 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -204,3 +204,65 @@ mod issue14991 {
         }],
     }
 }
+
+mod issue15018 {
+    fn used_later(a: i32, b: i32, c: i32) {
+        let x = 1;
+        {
+            let (x, y, z) = (a, b, c);
+            println!("{} {} {}", x, y, z);
+        }
+        println!("x = {x}");
+    }
+
+    fn not_used_later(a: i32, b: i32, c: i32) {
+        let (x, y, z) = (a, b, c);
+        println!("{} {} {}", x, y, z)
+    }
+
+    #[allow(irrefutable_let_patterns)]
+    fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) {
+        let (x, y, z) = (a, b, c);
+        println!("{} {} {}", x, y, z);
+        let x = 1;
+        println!("x = {x}");
+    }
+
+    #[allow(irrefutable_let_patterns)]
+    fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) {
+        let (x, y, z) = (a, b, c);
+        println!("{} {} {}", x, y, z);
+        if let (x, y, z) = (a, b, c) {
+            println!("{} {} {}", x, y, z)
+        }
+
+        {
+            let x: i32 = 1;
+            {
+                let (x, y, z) = (a, b, c);
+                println!("{} {} {}", x, y, z);
+            }
+            if let (x, y, z) = (a, x, c) {
+                println!("{} {} {}", x, y, z)
+            }
+        }
+
+        {
+            let (x, y, z) = (a, b, c);
+            println!("{} {} {}", x, y, z);
+            let fn_ = |y| {
+                println!("{} {} {}", a, b, y);
+            };
+            fn_(c);
+        }
+    }
+}
+
+#[allow(clippy::short_circuit_statement)]
+fn issue15269(a: usize, b: usize, c: usize) -> bool {
+    a < b
+        && b < c;
+
+    a < b
+        && b < c
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index d498da30fc8..ede1ab32beb 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -267,3 +267,79 @@ mod issue14991 {
         }],
     }
 }
+
+mod issue15018 {
+    fn used_later(a: i32, b: i32, c: i32) {
+        let x = 1;
+        match (a, b, c) {
+            //~^ match_single_binding
+            (x, y, z) => println!("{} {} {}", x, y, z),
+        }
+        println!("x = {x}");
+    }
+
+    fn not_used_later(a: i32, b: i32, c: i32) {
+        match (a, b, c) {
+            //~^ match_single_binding
+            (x, y, z) => println!("{} {} {}", x, y, z),
+        }
+    }
+
+    #[allow(irrefutable_let_patterns)]
+    fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) {
+        match (a, b, c) {
+            //~^ match_single_binding
+            (x, y, z) => println!("{} {} {}", x, y, z),
+        }
+        let x = 1;
+        println!("x = {x}");
+    }
+
+    #[allow(irrefutable_let_patterns)]
+    fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) {
+        match (a, b, c) {
+            //~^ match_single_binding
+            (x, y, z) => println!("{} {} {}", x, y, z),
+        }
+        if let (x, y, z) = (a, b, c) {
+            println!("{} {} {}", x, y, z)
+        }
+
+        {
+            let x: i32 = 1;
+            match (a, b, c) {
+                //~^ match_single_binding
+                (x, y, z) => println!("{} {} {}", x, y, z),
+            }
+            if let (x, y, z) = (a, x, c) {
+                println!("{} {} {}", x, y, z)
+            }
+        }
+
+        {
+            match (a, b, c) {
+                //~^ match_single_binding
+                (x, y, z) => println!("{} {} {}", x, y, z),
+            }
+            let fn_ = |y| {
+                println!("{} {} {}", a, b, y);
+            };
+            fn_(c);
+        }
+    }
+}
+
+#[allow(clippy::short_circuit_statement)]
+fn issue15269(a: usize, b: usize, c: usize) -> bool {
+    a < b
+        && match b {
+            //~^ match_single_binding
+            b => b < c,
+        };
+
+    a < b
+        && match (a, b) {
+            //~^ match_single_binding
+            (a, b) => b < c,
+        }
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr
index f274f80c81d..eea71777890 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.stderr
+++ b/src/tools/clippy/tests/ui/match_single_binding.stderr
@@ -411,5 +411,119 @@ LL ~             let _n = 1;
 LL +             42
    |
 
-error: aborting due to 29 previous errors
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:274:9
+   |
+LL | /         match (a, b, c) {
+LL | |
+LL | |             (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |         }
+   | |_________^
+   |
+help: consider using a `let` statement
+   |
+LL ~         {
+LL +             let (x, y, z) = (a, b, c);
+LL +             println!("{} {} {}", x, y, z);
+LL +         }
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:282:9
+   |
+LL | /         match (a, b, c) {
+LL | |
+LL | |             (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |         }
+   | |_________^
+   |
+help: consider using a `let` statement
+   |
+LL ~         let (x, y, z) = (a, b, c);
+LL +         println!("{} {} {}", x, y, z)
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:290:9
+   |
+LL | /         match (a, b, c) {
+LL | |
+LL | |             (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |         }
+   | |_________^
+   |
+help: consider using a `let` statement
+   |
+LL ~         let (x, y, z) = (a, b, c);
+LL +         println!("{} {} {}", x, y, z);
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:300:9
+   |
+LL | /         match (a, b, c) {
+LL | |
+LL | |             (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |         }
+   | |_________^
+   |
+help: consider using a `let` statement
+   |
+LL ~         let (x, y, z) = (a, b, c);
+LL +         println!("{} {} {}", x, y, z);
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:310:13
+   |
+LL | /             match (a, b, c) {
+LL | |
+LL | |                 (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |             }
+   | |_____________^
+   |
+help: consider using a `let` statement
+   |
+LL ~             {
+LL +                 let (x, y, z) = (a, b, c);
+LL +                 println!("{} {} {}", x, y, z);
+LL +             }
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:320:13
+   |
+LL | /             match (a, b, c) {
+LL | |
+LL | |                 (x, y, z) => println!("{} {} {}", x, y, z),
+LL | |             }
+   | |_____________^
+   |
+help: consider using a `let` statement
+   |
+LL ~             let (x, y, z) = (a, b, c);
+LL +             println!("{} {} {}", x, y, z);
+   |
+
+error: this match could be replaced by its body itself
+  --> tests/ui/match_single_binding.rs:335:12
+   |
+LL |           && match b {
+   |  ____________^
+LL | |
+LL | |             b => b < c,
+LL | |         };
+   | |_________^ help: consider using the match body instead: `b < c`
+
+error: this match could be replaced by its body itself
+  --> tests/ui/match_single_binding.rs:341:12
+   |
+LL |           && match (a, b) {
+   |  ____________^
+LL | |
+LL | |             (a, b) => b < c,
+LL | |         }
+   | |_________^ help: consider using the match body instead: `b < c`
+
+error: aborting due to 37 previous errors
 
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.rs b/src/tools/clippy/tests/ui/min_ident_chars.rs
index f473ac848a8..e2f82e2a182 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.rs
+++ b/src/tools/clippy/tests/ui/min_ident_chars.rs
@@ -124,3 +124,52 @@ fn wrong_pythagoras(a: f32, b: f32) -> f32 {
 mod issue_11163 {
     struct Array<T, const N: usize>([T; N]);
 }
+
+struct Issue13396;
+
+impl core::fmt::Display for Issue13396 {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        write!(f, "Issue13396")
+    }
+}
+
+impl core::fmt::Debug for Issue13396 {
+    fn fmt(&self, g: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        //~^ min_ident_chars
+        write!(g, "Issue13396")
+    }
+}
+
+fn issue13396() {
+    let a = |f: i8| f;
+    //~^ min_ident_chars
+    //~| min_ident_chars
+}
+
+trait D {
+    //~^ min_ident_chars
+    fn f(g: i32);
+    //~^ min_ident_chars
+    //~| min_ident_chars
+    fn long(long: i32);
+
+    fn g(arg: i8) {
+        //~^ min_ident_chars
+        fn c(d: u8) {}
+        //~^ min_ident_chars
+        //~| min_ident_chars
+    }
+}
+
+impl D for Issue13396 {
+    fn f(g: i32) {
+        fn h() {}
+        //~^ min_ident_chars
+        fn inner(a: i32) {}
+        //~^ min_ident_chars
+        let a = |f: String| f;
+        //~^ min_ident_chars
+        //~| min_ident_chars
+    }
+    fn long(long: i32) {}
+}
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr
index bd6c45cf648..36bf89e79f0 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.stderr
+++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr
@@ -193,5 +193,83 @@ error: this ident consists of a single char
 LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
    |                             ^
 
-error: aborting due to 32 previous errors
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:137:19
+   |
+LL |     fn fmt(&self, g: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+   |                   ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:144:14
+   |
+LL |     let a = |f: i8| f;
+   |              ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:144:9
+   |
+LL |     let a = |f: i8| f;
+   |         ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:149:7
+   |
+LL | trait D {
+   |       ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:151:10
+   |
+LL |     fn f(g: i32);
+   |          ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:151:8
+   |
+LL |     fn f(g: i32);
+   |        ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:156:8
+   |
+LL |     fn g(arg: i8) {
+   |        ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:158:12
+   |
+LL |         fn c(d: u8) {}
+   |            ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:158:14
+   |
+LL |         fn c(d: u8) {}
+   |              ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:166:12
+   |
+LL |         fn h() {}
+   |            ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:168:18
+   |
+LL |         fn inner(a: i32) {}
+   |                  ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:170:18
+   |
+LL |         let a = |f: String| f;
+   |                  ^
+
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:170:13
+   |
+LL |         let a = |f: String| f;
+   |             ^
+
+error: aborting due to 45 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
index 57d0f2b9948..fff6d2f34b8 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
@@ -1,5 +1,4 @@
-#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
-#![allow(clippy::needless_if, clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::needless_if)]
 #![warn(clippy::needless_collect)]
 //@no-rustfix
 use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
index c7bf1b14df8..24523c9f97b 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
@@ -1,5 +1,5 @@
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:9:39
+  --> tests/ui/needless_collect_indirect.rs:8:39
    |
 LL |     let indirect_iter = sample.iter().collect::<Vec<_>>();
    |                                       ^^^^^^^
@@ -18,7 +18,7 @@ LL ~     sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:13:38
+  --> tests/ui/needless_collect_indirect.rs:12:38
    |
 LL |     let indirect_len = sample.iter().collect::<VecDeque<_>>();
    |                                      ^^^^^^^
@@ -35,7 +35,7 @@ LL ~     sample.iter().count();
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:17:40
+  --> tests/ui/needless_collect_indirect.rs:16:40
    |
 LL |     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
    |                                        ^^^^^^^
@@ -52,7 +52,7 @@ LL ~     sample.iter().next().is_none();
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:21:43
+  --> tests/ui/needless_collect_indirect.rs:20:43
    |
 LL |     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
    |                                           ^^^^^^^
@@ -69,7 +69,7 @@ LL ~     sample.iter().any(|x| x == &5);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:35:48
+  --> tests/ui/needless_collect_indirect.rs:34:48
    |
 LL |     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
    |                                                ^^^^^^^
@@ -86,7 +86,7 @@ LL ~     sample.into_iter().any(|x| x == a);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:66:51
+  --> tests/ui/needless_collect_indirect.rs:65:51
    |
 LL |         let buffer: Vec<&str> = string.split('/').collect();
    |                                                   ^^^^^^^
@@ -103,7 +103,7 @@ LL ~         string.split('/').count()
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:73:55
+  --> tests/ui/needless_collect_indirect.rs:72:55
    |
 LL |         let indirect_len: VecDeque<_> = sample.iter().collect();
    |                                                       ^^^^^^^
@@ -120,7 +120,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:80:57
+  --> tests/ui/needless_collect_indirect.rs:79:57
    |
 LL |         let indirect_len: LinkedList<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -137,7 +137,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:87:57
+  --> tests/ui/needless_collect_indirect.rs:86:57
    |
 LL |         let indirect_len: BinaryHeap<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -154,7 +154,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:149:59
+  --> tests/ui/needless_collect_indirect.rs:148:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -172,7 +172,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == i);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:176:59
+  --> tests/ui/needless_collect_indirect.rs:175:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -190,7 +190,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:207:63
+  --> tests/ui/needless_collect_indirect.rs:206:63
    |
 LL |                 let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                               ^^^^^^^
@@ -208,7 +208,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:245:59
+  --> tests/ui/needless_collect_indirect.rs:244:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -226,7 +226,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:272:26
+  --> tests/ui/needless_collect_indirect.rs:271:26
    |
 LL |         let w = v.iter().collect::<Vec<_>>();
    |                          ^^^^^^^
@@ -244,7 +244,7 @@ LL ~         for _ in 0..v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:296:30
+  --> tests/ui/needless_collect_indirect.rs:295:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
@@ -262,7 +262,7 @@ LL ~         while 1 == v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> tests/ui/needless_collect_indirect.rs:320:30
+  --> tests/ui/needless_collect_indirect.rs:319:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index 1eecc3dee3d..cacce9a7d1c 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -236,3 +236,21 @@ mod issue14404 {
         }
     }
 }
+
+fn dont_simplify_double_not_if_types_differ() {
+    struct S;
+
+    impl std::ops::Not for S {
+        type Output = bool;
+        fn not(self) -> bool {
+            true
+        }
+    }
+
+    // The lint must propose `if !!S`, not `if S`.
+    // FIXME: `bool_comparison` will propose to use `S == true`
+    // which is invalid.
+    if !S != true {}
+    //~^ nonminimal_bool
+    //~| bool_comparison
+}
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index ecb82a23da0..c20412974b2 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -179,7 +179,7 @@ error: inequality checks against true can be replaced by a negation
   --> tests/ui/nonminimal_bool.rs:186:8
    |
 LL |     if !b != true {}
-   |        ^^^^^^^^^^ help: try simplifying it as shown: `!!b`
+   |        ^^^^^^^^^^ help: try simplifying it as shown: `b`
 
 error: this boolean expression can be simplified
   --> tests/ui/nonminimal_bool.rs:189:8
@@ -209,7 +209,7 @@ error: inequality checks against true can be replaced by a negation
   --> tests/ui/nonminimal_bool.rs:193:8
    |
 LL |     if true != !b {}
-   |        ^^^^^^^^^^ help: try simplifying it as shown: `!!b`
+   |        ^^^^^^^^^^ help: try simplifying it as shown: `b`
 
 error: this boolean expression can be simplified
   --> tests/ui/nonminimal_bool.rs:196:8
@@ -235,5 +235,17 @@ error: this boolean expression can be simplified
 LL |         if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) {
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!matches!(ty, TyKind::Ref(_, _, _)) || is_mutable(&expr)`
 
-error: aborting due to 31 previous errors
+error: this boolean expression can be simplified
+  --> tests/ui/nonminimal_bool.rs:253:8
+   |
+LL |     if !S != true {}
+   |        ^^^^^^^^^^ help: try: `S == true`
+
+error: inequality checks against true can be replaced by a negation
+  --> tests/ui/nonminimal_bool.rs:253:8
+   |
+LL |     if !S != true {}
+   |        ^^^^^^^^^^ help: try simplifying it as shown: `!!S`
+
+error: aborting due to 33 previous errors
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index fe3ac9e8f92..0f86de5646c 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -302,3 +302,15 @@ mod issue11059 {
         if let Some(o) = o { o } else { &S }
     }
 }
+
+fn issue15379() {
+    let opt = Some(0usize);
+    let opt_raw_ptr = &opt as *const Option<usize>;
+    let _ = unsafe { (*opt_raw_ptr).map_or(1, |o| o) };
+    //~^ option_if_let_else
+}
+
+fn issue15002() {
+    let res: Result<String, ()> = Ok("_".to_string());
+    let _ = res.map_or_else(|_| String::new(), |s| s.clone());
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 5b7498bc8e2..7aabd778f87 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -365,3 +365,19 @@ mod issue11059 {
         if let Some(o) = o { o } else { &S }
     }
 }
+
+fn issue15379() {
+    let opt = Some(0usize);
+    let opt_raw_ptr = &opt as *const Option<usize>;
+    let _ = unsafe { if let Some(o) = *opt_raw_ptr { o } else { 1 } };
+    //~^ option_if_let_else
+}
+
+fn issue15002() {
+    let res: Result<String, ()> = Ok("_".to_string());
+    let _ = match res {
+        //~^ option_if_let_else
+        Ok(s) => s.clone(),
+        Err(_) => String::new(),
+    };
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 9eb41f81a53..2e2fe6f2049 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -334,5 +334,22 @@ error: use Option::map_or_else instead of an if let/else
 LL |     let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() };
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())`
 
-error: aborting due to 25 previous errors
+error: use Option::map_or instead of an if let/else
+  --> tests/ui/option_if_let_else.rs:372:22
+   |
+LL |     let _ = unsafe { if let Some(o) = *opt_raw_ptr { o } else { 1 } };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*opt_raw_ptr).map_or(1, |o| o)`
+
+error: use Option::map_or_else instead of an if let/else
+  --> tests/ui/option_if_let_else.rs:378:13
+   |
+LL |       let _ = match res {
+   |  _____________^
+LL | |
+LL | |         Ok(s) => s.clone(),
+LL | |         Err(_) => String::new(),
+LL | |     };
+   | |_____^ help: try: `res.map_or_else(|_| String::new(), |s| s.clone())`
+
+error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
index 4143b8bfba5..802d27449ab 100644
--- a/src/tools/clippy/tests/ui/search_is_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some.rs
@@ -87,3 +87,18 @@ fn is_none() {
     let _ = (0..1).find(some_closure).is_none();
     //~^ search_is_some
 }
+
+#[allow(clippy::match_like_matches_macro)]
+fn issue15102() {
+    let values = [None, Some(3)];
+    let has_even = values
+        //~^ search_is_some
+        .iter()
+        .find(|v| match v {
+            Some(x) if x % 2 == 0 => true,
+            _ => false,
+        })
+        .is_some();
+
+    println!("{has_even}");
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index d9a43c8915e..d5412f90111 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -90,5 +90,20 @@ error: called `is_none()` after searching an `Iterator` with `find`
 LL |     let _ = (0..1).find(some_closure).is_none();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)`
 
-error: aborting due to 8 previous errors
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some.rs:94:20
+   |
+LL |       let has_even = values
+   |  ____________________^
+LL | |
+LL | |         .iter()
+LL | |         .find(|v| match v {
+...  |
+LL | |         })
+LL | |         .is_some();
+   | |__________________^
+   |
+   = help: this is more succinctly expressed by calling `any()`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
index 42b39b33b57..c7a4422f373 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
@@ -289,3 +289,10 @@ mod issue9120 {
         //~^ search_is_some
     }
 }
+
+fn issue15102() {
+    let values = [None, Some(3)];
+    let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0));
+    //~^ search_is_some
+    println!("{has_even}");
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
index ca4f4d941cb..d6b1c67c971 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
@@ -297,3 +297,10 @@ mod issue9120 {
         //~^ search_is_some
     }
 }
+
+fn issue15102() {
+    let values = [None, Some(3)];
+    let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
+    //~^ search_is_some
+    println!("{has_even}");
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
index 8291f48d43c..551a670d937 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
@@ -289,5 +289,11 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |         let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
 
-error: aborting due to 46 previous errors
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_some.rs:303:34
+   |
+LL |     let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))`
+
+error: aborting due to 47 previous errors
 
diff --git a/src/tools/clippy/tests/ui/string_to_string.rs b/src/tools/clippy/tests/ui/string_to_string.rs
deleted file mode 100644
index 7c5bd8a897b..00000000000
--- a/src/tools/clippy/tests/ui/string_to_string.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#![warn(clippy::string_to_string)]
-#![allow(clippy::redundant_clone, clippy::unnecessary_literal_unwrap)]
-
-fn main() {
-    let mut message = String::from("Hello");
-    let mut v = message.to_string();
-    //~^ string_to_string
-
-    let variable1 = String::new();
-    let v = &variable1;
-    let variable2 = Some(v);
-    let _ = variable2.map(|x| {
-        println!();
-        x.to_string()
-    });
-    //~^^ string_to_string
-
-    let x = Some(String::new());
-    let _ = x.unwrap_or_else(|| v.to_string());
-    //~^ string_to_string
-}
diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr
deleted file mode 100644
index 99eea06f18e..00000000000
--- a/src/tools/clippy/tests/ui/string_to_string.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string.rs:6:17
-   |
-LL |     let mut v = message.to_string();
-   |                 ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using `.clone()`
-   = note: `-D clippy::string-to-string` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::string_to_string)]`
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string.rs:14:9
-   |
-LL |         x.to_string()
-   |         ^^^^^^^^^^^^^
-   |
-   = help: consider using `.clone()`
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string.rs:19:33
-   |
-LL |     let _ = x.unwrap_or_else(|| v.to_string());
-   |                                 ^^^^^^^^^^^^^
-   |
-   = help: consider using `.clone()`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.fixed b/src/tools/clippy/tests/ui/string_to_string_in_map.fixed
deleted file mode 100644
index efc085539f1..00000000000
--- a/src/tools/clippy/tests/ui/string_to_string_in_map.fixed
+++ /dev/null
@@ -1,20 +0,0 @@
-#![deny(clippy::string_to_string)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)]
-
-fn main() {
-    let variable1 = String::new();
-    let v = &variable1;
-    let variable2 = Some(v);
-    let _ = variable2.cloned();
-    //~^ string_to_string
-    let _ = variable2.cloned();
-    //~^ string_to_string
-    #[rustfmt::skip]
-    let _ = variable2.cloned();
-    //~^ string_to_string
-
-    let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>();
-    //~^ string_to_string
-    let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>();
-    //~^ string_to_string
-}
diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.rs b/src/tools/clippy/tests/ui/string_to_string_in_map.rs
deleted file mode 100644
index 5bf1d7ba5a2..00000000000
--- a/src/tools/clippy/tests/ui/string_to_string_in_map.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![deny(clippy::string_to_string)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)]
-
-fn main() {
-    let variable1 = String::new();
-    let v = &variable1;
-    let variable2 = Some(v);
-    let _ = variable2.map(String::to_string);
-    //~^ string_to_string
-    let _ = variable2.map(|x| x.to_string());
-    //~^ string_to_string
-    #[rustfmt::skip]
-    let _ = variable2.map(|x| { x.to_string() });
-    //~^ string_to_string
-
-    let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>();
-    //~^ string_to_string
-    let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>();
-    //~^ string_to_string
-}
diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.stderr b/src/tools/clippy/tests/ui/string_to_string_in_map.stderr
deleted file mode 100644
index 35aeed656ee..00000000000
--- a/src/tools/clippy/tests/ui/string_to_string_in_map.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string_in_map.rs:8:23
-   |
-LL |     let _ = variable2.map(String::to_string);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()`
-   |
-note: the lint level is defined here
-  --> tests/ui/string_to_string_in_map.rs:1:9
-   |
-LL | #![deny(clippy::string_to_string)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string_in_map.rs:10:23
-   |
-LL |     let _ = variable2.map(|x| x.to_string());
-   |                       ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()`
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string_in_map.rs:13:23
-   |
-LL |     let _ = variable2.map(|x| { x.to_string() });
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()`
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string_in_map.rs:16:40
-   |
-LL |     let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>();
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()`
-
-error: `to_string()` called on a `String`
-  --> tests/ui/string_to_string_in_map.rs:18:40
-   |
-LL |     let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>();
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()`
-
-error: aborting due to 5 previous errors
-
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
index 28a3b551116..072e7b27b0d 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_suspicious_else_formatting.rs
 
-#![warn(clippy::suspicious_else_formatting)]
+#![warn(clippy::suspicious_else_formatting, clippy::possible_missing_else)]
 #![allow(
     clippy::if_same_then_else,
     clippy::let_unit_value,
@@ -20,12 +20,12 @@ fn main() {
     // weird `else` formatting:
     if foo() {
     } {
-    //~^ suspicious_else_formatting
+    //~^ possible_missing_else
     }
 
     if foo() {
     } if foo() {
-    //~^ suspicious_else_formatting
+    //~^ possible_missing_else
     }
 
     let _ = { // if as the last expression
@@ -33,7 +33,7 @@ fn main() {
 
         if foo() {
         } if foo() {
-        //~^ suspicious_else_formatting
+        //~^ possible_missing_else
         }
         else {
         }
@@ -42,7 +42,7 @@ fn main() {
     let _ = { // if in the middle of a block
         if foo() {
         } if foo() {
-        //~^ suspicious_else_formatting
+        //~^ possible_missing_else
         }
         else {
         }
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
index affd20b22d9..04555c6edbd 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
@@ -5,8 +5,8 @@ LL |     } {
    |      ^
    |
    = note: to remove this lint, add the missing `else` or add a new line before the next block
-   = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::suspicious_else_formatting)]`
+   = note: `-D clippy::possible-missing-else` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::possible_missing_else)]`
 
 error: this looks like an `else if` but the `else` is missing
   --> tests/ui/suspicious_else_formatting.rs:27:6
@@ -41,6 +41,8 @@ LL | |     {
    | |____^
    |
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
+   = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::suspicious_else_formatting)]`
 
 error: this is an `else if` but the formatting might hide it
   --> tests/ui/suspicious_else_formatting.rs:67:6
diff --git a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
index e7e01248dfb..65f67df7913 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
@@ -1,5 +1,6 @@
 //@no-rustfix
 
+#![allow(clippy::duplicated_attributes)]
 #![warn(clippy::unnecessary_clippy_cfg)]
 #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ unnecessary_clippy_cfg
@@ -7,7 +8,6 @@
 //~^ unnecessary_clippy_cfg
 #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ unnecessary_clippy_cfg
-//~| duplicated_attributes
 #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ unnecessary_clippy_cfg
 
@@ -17,7 +17,6 @@
 //~^ unnecessary_clippy_cfg
 #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ unnecessary_clippy_cfg
-//~| duplicated_attributes
 #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ unnecessary_clippy_cfg
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
index f66c6894954..4f638d5c513 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
@@ -1,5 +1,5 @@
 error: no need to put clippy lints behind a `clippy` cfg
-  --> tests/ui/unnecessary_clippy_cfg.rs:4:1
+  --> tests/ui/unnecessary_clippy_cfg.rs:5:1
    |
 LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]`
@@ -8,7 +8,7 @@ LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_clippy_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
-  --> tests/ui/unnecessary_clippy_cfg.rs:6:37
+  --> tests/ui/unnecessary_clippy_cfg.rs:7:37
    |
 LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    = note: write instead: `#![deny(clippy::non_minimal_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
-  --> tests/ui/unnecessary_clippy_cfg.rs:8:37
+  --> tests/ui/unnecessary_clippy_cfg.rs:9:37
    |
 LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,46 +52,10 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    = note: write instead: `#[deny(clippy::non_minimal_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
-  --> tests/ui/unnecessary_clippy_cfg.rs:21:1
+  --> tests/ui/unnecessary_clippy_cfg.rs:20:1
    |
 LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]`
 
-error: duplicated attribute
-  --> tests/ui/unnecessary_clippy_cfg.rs:8:26
-   |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                          ^^^^^^^^^
-   |
-note: first defined here
-  --> tests/ui/unnecessary_clippy_cfg.rs:6:26
-   |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                          ^^^^^^^^^
-help: remove this attribute
-  --> tests/ui/unnecessary_clippy_cfg.rs:8:26
-   |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                          ^^^^^^^^^
-   = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
-
-error: duplicated attribute
-  --> tests/ui/unnecessary_clippy_cfg.rs:18:25
-   |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                         ^^^^^^^^^
-   |
-note: first defined here
-  --> tests/ui/unnecessary_clippy_cfg.rs:16:25
-   |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                         ^^^^^^^^^
-help: remove this attribute
-  --> tests/ui/unnecessary_clippy_cfg.rs:18:25
-   |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
-   |                         ^^^^^^^^^
-
-error: aborting due to 10 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
index 3109c4af8e2..10552431d65 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
@@ -131,6 +131,26 @@ fn issue14201(a: Option<String>, b: Option<String>, s: &String) -> bool {
     x && y
 }
 
+fn issue14714() {
+    assert!(Some("test") == Some("test"));
+    //~^ unnecessary_map_or
+
+    // even though we're in a macro context, we still need to parenthesise because of the `then`
+    assert!((Some("test") == Some("test")).then(|| 1).is_some());
+    //~^ unnecessary_map_or
+
+    // method lints don't fire on macros
+    macro_rules! m {
+        ($x:expr) => {
+            // should become !($x == Some(1))
+            let _ = !$x.map_or(false, |v| v == 1);
+            // should become $x == Some(1)
+            let _ = $x.map_or(false, |v| v == 1);
+        };
+    }
+    m!(Some(5));
+}
+
 fn issue15180() {
     let s = std::sync::Mutex::new(Some("foo"));
     _ = s.lock().unwrap().is_some_and(|s| s == "foo");
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
index 52a55f9fc9e..4b406ec2998 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
@@ -135,6 +135,26 @@ fn issue14201(a: Option<String>, b: Option<String>, s: &String) -> bool {
     x && y
 }
 
+fn issue14714() {
+    assert!(Some("test").map_or(false, |x| x == "test"));
+    //~^ unnecessary_map_or
+
+    // even though we're in a macro context, we still need to parenthesise because of the `then`
+    assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some());
+    //~^ unnecessary_map_or
+
+    // method lints don't fire on macros
+    macro_rules! m {
+        ($x:expr) => {
+            // should become !($x == Some(1))
+            let _ = !$x.map_or(false, |v| v == 1);
+            // should become $x == Some(1)
+            let _ = $x.map_or(false, |v| v == 1);
+        };
+    }
+    m!(Some(5));
+}
+
 fn issue15180() {
     let s = std::sync::Mutex::new(Some("foo"));
     _ = s.lock().unwrap().map_or(false, |s| s == "foo");
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
index 99e17e8b34b..b8a22346c37 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
@@ -327,7 +327,31 @@ LL +     let y = b.is_none_or(|b| b == *s);
    |
 
 error: this `map_or` can be simplified
-  --> tests/ui/unnecessary_map_or.rs:140:9
+  --> tests/ui/unnecessary_map_or.rs:139:13
+   |
+LL |     assert!(Some("test").map_or(false, |x| x == "test"));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use a standard comparison instead
+   |
+LL -     assert!(Some("test").map_or(false, |x| x == "test"));
+LL +     assert!(Some("test") == Some("test"));
+   |
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:143:13
+   |
+LL |     assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use a standard comparison instead
+   |
+LL -     assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some());
+LL +     assert!((Some("test") == Some("test")).then(|| 1).is_some());
+   |
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:160:9
    |
 LL |     _ = s.lock().unwrap().map_or(false, |s| s == "foo");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -339,7 +363,7 @@ LL +     _ = s.lock().unwrap().is_some_and(|s| s == "foo");
    |
 
 error: this `map_or` can be simplified
-  --> tests/ui/unnecessary_map_or.rs:144:9
+  --> tests/ui/unnecessary_map_or.rs:164:9
    |
 LL |     _ = s.map_or(false, |s| s == "foo");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -350,5 +374,5 @@ LL -     _ = s.map_or(false, |s| s == "foo");
 LL +     _ = s.is_some_and(|s| s == "foo");
    |
 
-error: aborting due to 28 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
index 9a38d3746da..a066554037f 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
@@ -7,7 +7,7 @@ LL |     vec.sort_by(|a, b| a.cmp(b));
    = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]`
 
-error: consider using `sort`
+error: consider using `sort_unstable`
   --> tests/ui/unnecessary_sort_by.rs:14:5
    |
 LL |     vec.sort_unstable_by(|a, b| a.cmp(b));
@@ -19,7 +19,7 @@ error: consider using `sort_by_key`
 LL |     vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())`
 
-error: consider using `sort_by_key`
+error: consider using `sort_unstable_by_key`
   --> tests/ui/unnecessary_sort_by.rs:18:5
    |
 LL |     vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b)));
@@ -31,7 +31,7 @@ error: consider using `sort_by_key`
 LL |     vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))`
 
-error: consider using `sort_by_key`
+error: consider using `sort_unstable_by_key`
   --> tests/ui/unnecessary_sort_by.rs:24:5
    |
 LL |     vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a)));
@@ -43,7 +43,7 @@ error: consider using `sort_by_key`
 LL |     vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())`
 
-error: consider using `sort_by_key`
+error: consider using `sort_unstable_by_key`
   --> tests/ui/unnecessary_sort_by.rs:37:5
    |
 LL |     vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs()));
@@ -55,7 +55,7 @@ error: consider using `sort_by_key`
 LL |         args.sort_by(|a, b| a.name().cmp(&b.name()));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())`
 
-error: consider using `sort_by_key`
+error: consider using `sort_unstable_by_key`
   --> tests/ui/unnecessary_sort_by.rs:99:9
    |
 LL |         args.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
@@ -67,7 +67,7 @@ error: consider using `sort_by_key`
 LL |         args.sort_by(|a, b| b.name().cmp(&a.name()));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))`
 
-error: consider using `sort_by_key`
+error: consider using `sort_unstable_by_key`
   --> tests/ui/unnecessary_sort_by.rs:104:9
    |
 LL |         args.sort_unstable_by(|a, b| b.name().cmp(&a.name()));
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index a62b6269a3b..805baf2af6d 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -54,7 +54,6 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB
 users_on_vacation = [
     "matthiaskrgr",
     "Manishearth",
-    "samueltardieu",
 ]
 
 [assign.owners]
diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html
index 5d65ea585df..d34ff0a5973 100644
--- a/src/tools/clippy/util/gh-pages/index_template.html
+++ b/src/tools/clippy/util/gh-pages/index_template.html
@@ -14,7 +14,6 @@ Otherwise, have a great day =^.^=
 
     <title>Clippy Lints</title> {# #}
 
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"/> {# #}
     <link id="githubLightHighlight" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github.min.css" disabled="true" /> {# #}
     <link id="githubDarkHighlight" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github-dark.min.css" disabled="true" /> {# #}
 
@@ -49,7 +48,7 @@ Otherwise, have a great day =^.^=
     <script src="theme.js"></script> {# #}
 
     <div class="container"> {# #}
-        <h1 class="page-header">Clippy Lints <span id="lint-count" class="badge"></span></h1> {# #}
+        <h1 class="page-header">Clippy Lints <span class="badge">Total number: {{+ count }}</span></h1> {# #}
 
         <noscript> {# #}
             <div class="alert alert-danger" role="alert"> {# #}
@@ -59,9 +58,9 @@ Otherwise, have a great day =^.^=
 
         <div id="menu-filters"> {# #}
             <div class="panel-body row"> {# #}
-                <div id="upper-filters" class="col-12 col-md-5"> {# #}
-                    <div class="btn-group" id="lint-levels" tabindex="-1"> {# #}
-                        <button type="button" class="btn btn-default dropdown-toggle"> {# #}
+                <div id="upper-filters"> {# #}
+                    <div id="lint-levels" tabindex="-1"> {# #}
+                        <button type="button" class="btn-default dropdown-toggle"> {# #}
                             Lint levels <span class="badge">4</span> <span class="caret"></span> {# #}
                         </button> {# #}
                         <ul class="dropdown-menu" id="lint-levels-selector"> {# #}
@@ -74,8 +73,8 @@ Otherwise, have a great day =^.^=
                             <li role="separator" class="divider"></li> {# #}
                         </ul> {# #}
                     </div> {# #}
-                    <div class="btn-group" id="lint-groups" tabindex="-1"> {# #}
-                        <button type="button" class="btn btn-default dropdown-toggle"> {# #}
+                    <div id="lint-groups" tabindex="-1"> {# #}
+                        <button type="button" class="btn-default dropdown-toggle"> {# #}
                             Lint groups <span class="badge">9</span> <span class="caret"></span> {# #}
                         </button> {# #}
                         <ul class="dropdown-menu" id="lint-groups-selector"> {# #}
@@ -91,8 +90,8 @@ Otherwise, have a great day =^.^=
                             <li role="separator" class="divider"></li> {# #}
                         </ul> {# #}
                     </div> {# #}
-                    <div class="btn-group" id="version-filter" tabindex="-1"> {# #}
-                        <button type="button" class="btn btn-default dropdown-toggle"> {# #}
+                    <div id="version-filter" tabindex="-1"> {# #}
+                        <button type="button" class="btn-default dropdown-toggle"> {# #}
                             Version {#+ #}
                             <span id="version-filter-count" class="badge">0</span> {#+ #}
                             <span class="caret"></span> {# #}
@@ -104,8 +103,8 @@ Otherwise, have a great day =^.^=
                             <li role="separator" class="divider"></li> {# #}
                         </ul> {# #}
                     </div> {# #}
-                    <div class="btn-group" id="lint-applicabilities" tabindex="-1"> {# #}
-                        <button type="button" class="btn btn-default dropdown-toggle"> {# #}
+                    <div id="lint-applicabilities" tabindex="-1"> {# #}
+                        <button type="button" class="btn-default dropdown-toggle"> {# #}
                             Applicability {#+ #}
                             <span class="badge">4</span> {#+ #}
                             <span class="caret"></span> {# #}
@@ -121,22 +120,20 @@ Otherwise, have a great day =^.^=
                         </ul> {# #}
                     </div> {# #}
                 </div> {# #}
-                <div class="col-12 col-md-5 search-control"> {# #}
+                <div class="search-control"> {# #}
                     <div class="input-group"> {# #}
                         <label class="input-group-addon" id="filter-label" for="search-input">Filter:</label> {# #}
                         <input type="text" class="form-control filter-input" placeholder="Keywords or search string (`S` or `/` to focus)" id="search-input" /> {# #}
-                        <span class="input-group-btn"> {# #}
-                            <button class="filter-clear btn" type="button" onclick="searchState.clearInput(event)"> {# #}
-                                Clear {# #}
-                            </button> {# #}
-                        </span> {# #}
+                        <button class="filter-clear" type="button" onclick="searchState.clearInput(event)"> {# #}
+                            Clear {# #}
+                        </button> {# #}
                     </div> {# #}
                 </div> {# #}
-                <div class="col-12 col-md-2 btn-group expansion-group"> {# #}
-                    <button title="Collapse All" class="btn btn-default expansion-control" type="button" id="collapse-all"> {# #}
+                <div class="btn-group expansion-group"> {# #}
+                    <button title="Collapse All" class="btn-default expansion-control" type="button" id="collapse-all"> {# #}
                         <span class="glyphicon glyphicon-collapse-up"></span> {# #}
                     </button> {# #}
-                    <button title="Expand All" class="btn btn-default expansion-control" type="button" id="expand-all"> {# #}
+                    <button title="Expand All" class="btn-default expansion-control" type="button" id="expand-all"> {# #}
                         <span class="glyphicon glyphicon-collapse-down"></span> {# #}
                     </button> {# #}
                 </div> {# #}
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index d3204967531..2b6ee67c37d 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -208,6 +208,7 @@ const LEVEL_FILTERS_DEFAULT = {
     allow: true,
     warn: true,
     deny: true,
+    none: true,
 };
 const APPLICABILITIES_FILTER_DEFAULT = {
     Unspecified: true,
@@ -592,20 +593,8 @@ disableShortcutsButton.checked = disableShortcuts;
 
 addListeners();
 highlightLazily();
-
-function updateLintCount() {
-    const allLints = filters.getAllLints().filter(lint => lint.group != "deprecated");
-    const totalLints = allLints.length;
-
-    const countElement = document.getElementById("lint-count");
-    if (countElement) {
-        countElement.innerText = `Total number: ${totalLints}`;
-    }
-}
-
 generateSettings();
 generateSearch();
 parseURLFilters();
 scrollToLintByURL();
 filters.filterLints();
-updateLintCount();
diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css
index 66abf4598b0..2cf93b2a71d 100644
--- a/src/tools/clippy/util/gh-pages/style.css
+++ b/src/tools/clippy/util/gh-pages/style.css
@@ -1,13 +1,73 @@
+body {
+    --icon-filter: initial;
+}
+
+body.ayu {
+    --icon-filter: invert(100%);
+}
+
+* {
+    box-sizing: border-box;
+}
+
 blockquote { font-size: 1em; }
 
+h1, h2, h3, h4, h5, h6 {
+    font-family: inherit;
+    font-weight: 500;
+    line-height: 1.1;
+    color: inherit;
+}
+h1 {
+    font-size: 36px;
+}
+
+a {
+    color: #337ab7;
+    text-decoration: none;
+}
+
+button {
+    cursor: pointer;
+    margin: 0;
+    font-family: inherit;
+    font-size: inherit;
+    line-height: inherit;
+}
+
+label {
+    display: inline-block;
+    max-width: 100%;
+}
+
 .dropdown-menu {
     color: var(--fg);
     background: var(--theme-popup-bg);
     border: 1px solid var(--theme-popup-border);
+    border-radius: 4px;
+    position: absolute;
+    top: 100%;
+    left: 0;
+    z-index: 1000;
+    display: none;
+    float: left;
+    min-width: 160px;
+    padding: 5px 0;
+    margin: 2px 0 0;
+    font-size: 14px;
+    text-align: left;
+    list-style: none;
+    box-shadow: 0 6px 12px rgba(0,0,0,.175);
+}
+.open > .dropdown-menu {
+  display: block;
 }
 
 .dropdown-menu .divider {
     background-color: var(--theme-popup-border);
+    height: 1px;
+    margin: 9px 0;
+    overflow: hidden;
 }
 
 .dropdown-menu .checkbox {
@@ -30,18 +90,49 @@ blockquote { font-size: 1em; }
     background-color: var(--theme-hover);
 }
 
+.checkbox label {
+    min-height: 20px;
+    margin-bottom: 0;
+    font-weight: 400;
+    cursor: pointer;
+}
+
+.text-capitalize {
+    text-transform: capitalize;
+}
+
+.container {
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+.container::before {
+    display: table;
+    content: " ";
+}
 .container > * {
-  margin-bottom: 20px;
-  border-radius: 4px;
-  background: var(--bg);
-  border: 1px solid var(--theme-popup-border);
-  box-shadow: 0 1px 1px rgba(0,0,0,.05);
+    margin-bottom: 20px;
+    border-radius: 4px;
+    background: var(--bg);
+    border: 1px solid var(--theme-popup-border);
+    box-shadow: 0 1px 1px rgba(0,0,0,.05);
 }
 
+div.panel-body {
+    padding: 15px;
+}
+div.panel-body::before, div.panel-body::after {
+    display: table;
+    content: " ";
+}
+div.panel-body::after {
+    clear: both;
+}
 div.panel-body button {
     background: var(--searchbar-bg);
-    color: var(--searchbar-fg);
     border-color: var(--theme-popup-border);
+    color: var(--searchbar-fg);
 }
 
 div.panel-body button:hover {
@@ -52,9 +143,79 @@ div.panel-body  button.open {
     filter: brightness(90%);
 }
 
-.dropdown-toggle .badge {
+.row {
+    margin-right: -15px;
+    margin-left: -15px;
+}
+
+#upper-filters {
+    position: relative;
+    min-height: 1px;
+    padding-right: 15px;
+    padding-left: 15px;
+}
+
+#upper-filters > * {
+    position: relative;
+}
+
+.btn-group {
+    position: relative;
+    display: inline-block;
+}
+button {
+    display: inline-block;
+    padding: 6px 12px;
+    margin-bottom: 0;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 1.42857143;
+    text-align: center;
+    white-space: nowrap;
+    vertical-align: middle;
+    touch-action: manipulation;
+    cursor: pointer;
+    user-select: none;
+    border: 1px solid transparent;
+    border-radius: 4px;
+}
+button:hover {
+    text-decoration: none;
+}
+.badge {
+    color: #fff;
+    position: relative;
+    top: -1px;
+    display: inline-block;
+    min-width: 10px;
+    padding: 3px 7px;
+    font-size: 12px;
+    font-weight: 700;
+    line-height: 1;
+    text-align: center;
+    white-space: nowrap;
+    vertical-align: middle;
+    border-radius: 10px;
     background-color: #777;
 }
+.btn-default:hover {
+    color: #333;
+    background-color: #e6e6e6;
+    border-color: #adadad;
+}
+.btn-default .badge {
+    color: #fff;
+}
+button .caret {
+    display: inline-block;
+    width: 0;
+    height: 0;
+    margin-left: 0;
+    vertical-align: middle;
+    border-top: 4px dashed;
+    border-right: 4px solid transparent;
+    border-left: 4px solid transparent;
+}
 
 .lint-title {
     cursor: pointer;
@@ -81,12 +242,93 @@ article:hover .panel-title-name .anchor { display: inline;}
 
 .search-control {
     margin-top: 15px;
+    position: relative;
+    min-height: 1px;
+    padding-right: 15px;
+    padding-left: 15px;
 }
 
-@media (min-width: 992px) {
-    .search-control {
-        margin-top: 0;
-    }
+.input-group {
+    position: relative;
+    display: flex;
+}
+.input-group > :last-child {
+    border-left: 0;
+}
+.input-group > :first-child, .btn-group > :first-child {
+    border-right: 0;
+    border-top-right-radius: 0;
+    border-bottom-right-radius: 0;
+}
+.input-group > :last-child, .btn-group > :last-child {
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+.input-group .form-control:not(:first-child):not(:last-child) {
+    border-radius: 0;
+}
+.form-control:focus {
+    border-color: #66afe9;
+    outline: 0;
+    box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
+}
+.input-group-addon {
+    padding: 6px 12px;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 1;
+    text-align: center;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    white-space: nowrap;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.glyphicon.glyphicon-collapse-up::before, .glyphicon.glyphicon-collapse-down::before {
+    --background-img-size: 14px;
+    background-repeat: no-repeat;
+    background-size: var(--background-img-size);
+    height: calc(var(--background-img-size) + 6px);
+    display: block;
+    background-position: 50%;
+    content: "";
+    filter: var(--icon-filter);
+}
+.glyphicon.glyphicon-collapse-up:hover::before, .glyphicon.glyphicon-collapse-down:hover::before {
+    filter: initial;
+}
+.glyphicon.glyphicon-collapse-up::before {
+    /* Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License -
+       https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. */
+    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 \
+        448 512"><path d="M64 80c-8.8 0-16 7.2-16 16l0 320c0 8.8 7.2 16 16 16l320 0c8.8 0 16-7.2 \
+        16-16l0-320c0-8.8-7.2-16-16-16L64 80zM0 96C0 60.7 28.7 32 64 32l320 0c35.3 0 64 28.7 64 \
+        64l0 320c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96zm224 64c6.7 0 13 2.8 17.6 \
+        7.7l104 112c6.5 7 8.2 17.2 4.4 25.9s-12.5 14.4-22 14.4l-208 0c-9.5 0-18.2-5.7-22-14.4s-2.\
+        1-18.9 4.4-25.9l104-112c4.5-4.9 10.9-7.7 17.6-7.7z"/></svg>');
+}
+.glyphicon.glyphicon-collapse-down::before {
+    /* Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License -
+       https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. */
+    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \
+        viewBox="0 0 448 512"><path d="M384 432c8.8 0 16-7.2 16-16l0-320c0-8.8-7.2-16-16-16L64 \
+        80c-8.8 0-16 7.2-16 16l0 320c0 8.8 7.2 16 16 16l320 0zm64-16c0 35.3-28.7 64-64 64L64 \
+        480c-35.3 0-64-28.7-64-64L0 96C0 60.7 28.7 32 64 32l320 0c35.3 0 64 28.7 64 64l0 320zM224 \
+        352c-6.7 0-13-2.8-17.6-7.7l-104-112c-6.5-7-8.2-17.2-4.4-25.9s12.5-14.4 22-14.4l208 0c9.5 0 \
+        18.2 5.7 22 14.4s2.1 18.9-4.4 25.9l-104 112c-4.5 4.9-10.9 7.7-17.6 7.7z"/></svg>');
+}
+
+.expansion-group {
+    margin-top: 15px;
+    padding: 0px 8px;
+    display: flex;
+    flex-wrap: nowrap;
+}
+
+.expansion-control {
+    width: 50%;
 }
 
 @media (min-width: 405px) {
@@ -96,6 +338,38 @@ article:hover .panel-title-name .anchor { display: inline;}
     }
 }
 
+@media (min-width: 768px) {
+    .container {
+        width: 750px;
+    }
+}
+
+@media (min-width: 992px) {
+    .search-control {
+        margin-top: 0;
+    }
+    .container {
+        width: 970px;
+    }
+    #upper-filters, .search-control, .expansion-group {
+        float: left;
+    }
+    #upper-filters, .search-control {
+        width: 41.66666667%;
+    }
+    .expansion-group {
+        margin-top: 0;
+        padding: 0px 15px;
+        width: 16.66666667%;
+    }
+}
+
+@media (min-width: 1200px) {
+    .container {
+        width: 1170px;
+    }
+}
+
 @media (max-width: 430px) {
     /* Turn the version filter list to the left */
     #version-filter-selector {
@@ -113,8 +387,20 @@ article:hover .panel-title-name .anchor { display: inline;}
 }
 
 .label {
-    padding-top: 0.3em;
-    padding-bottom: 0.3em;
+    padding: 0.3em 0.6em;
+    font-size: 75%;
+    font-weight: 700;
+    line-height: 1;
+    color: #fff;
+    text-align: center;
+    white-space: nowrap;
+    vertical-align: baseline;
+    border-radius: .25em;
+    text-decoration: none;
+}
+
+.label-default {
+    background-color: #777;
 }
 
 .lint-level {
@@ -207,11 +493,6 @@ article:hover .panel-title-name .anchor { display: inline;}
     font-family: monospace;
 }
 
-details {
-    border-radius: 4px;
-    padding: .5em .5em 0;
-}
-
 pre {
     padding: 0;
 }
@@ -223,10 +504,6 @@ summary {
     display: revert;
 }
 
-details[open] {
-    padding: .5em;
-}
-
 /* Expanding the mdBook theme*/
 .light, body:not([class]) {
     --inline-code-bg: #f6f7f6;
@@ -307,13 +584,13 @@ L4.75,12h2.5l0.5393066-2.1572876  c0.2276001-0.1062012,0.4459839-0.2269287,0.649
 -0.3701782l2.1323853,0.6099854l1.25-2.1650391L10.2133789,6.362915  C10.2238159,6.241333,\
 10.25,6.1243286,10.25,6z M6,7.5C5.1715698,7.5,4.5,6.8284302,4.5,6S5.1715698,4.5,6,4.5S7.5\
 ,5.1715698,7.5,6  S6.8284302,7.5,6,7.5z" fill="black"/></svg>');
-  width: 18px;
-  height: 18px;
-  display: block;
-  filter: invert(0.7);
-  position: absolute;
-  top: 4px;
-  left: 5px;
+    width: 18px;
+    height: 18px;
+    display: block;
+    filter: invert(0.7);
+    position: absolute;
+    top: 4px;
+    left: 5px;
 }
 
 .settings-menu * {
@@ -350,6 +627,7 @@ L4.75,12h2.5l0.5393066-2.1572876  c0.2276001-0.1062012,0.4459839-0.2269287,0.649
     border-bottom: 1px solid var(--theme-popup-border);
     padding-bottom: 19px;
     border-radius: 0;
+    margin: 40px 0 20px;
 }
 pre, hr {
     background: var(--bg);
@@ -401,7 +679,16 @@ ul.dropdown-menu li.checkbox > button:hover {
 .filter-input {
     background: var(--searchbar-bg);
     color: var(--searchbar-fg);
-    border-color: var(--theme-popup-border);
+    position: relative;
+    width: 100%;
+    margin-bottom: 0;
+    height: 34px;
+    padding: 6px 12px;
+    font-size: 14px;
+    line-height: 1.42857143;
+    border: 1px solid var(--theme-popup-border);
+    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+    transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
 }
 
 .filter-input::-webkit-input-placeholder,
@@ -410,24 +697,6 @@ ul.dropdown-menu li.checkbox > button:hover {
     opacity: 30%;
 }
 
-.expansion-group {
-    margin-top: 15px;
-    padding: 0px 8px;
-    display: flex;
-    flex-wrap: nowrap;
-}
-
-@media (min-width: 992px) {
-    .expansion-group {
-        margin-top: 0;
-        padding: 0px 15px;
-    }
-}
-
-.expansion-control {
-    width: 50%;
-}
-
 :not(pre) > code {
     color: var(--inline-code-color);
     background-color: var(--inline-code-bg);
@@ -438,6 +707,10 @@ html {
 body {
     background: var(--bg);
     color: var(--fg);
+    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-size: 14px;
+    line-height: 1.42857143;
+    margin: 0;
 }
 
 article > label {
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 30d8537b51a..33a02eb29fd 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -637,6 +637,7 @@ fn matches_env() {
         ("x86_64-unknown-linux-gnu", "gnu"),
         ("x86_64-fortanix-unknown-sgx", "sgx"),
         ("arm-unknown-linux-musleabi", "musl"),
+        ("aarch64-apple-ios-macabi", "macabi"),
     ];
     for (target, env) in envs {
         let config: Config = cfg().target(target).build();
@@ -647,11 +648,7 @@ fn matches_env() {
 
 #[test]
 fn matches_abi() {
-    let abis = [
-        ("aarch64-apple-ios-macabi", "macabi"),
-        ("x86_64-unknown-linux-gnux32", "x32"),
-        ("arm-unknown-linux-gnueabi", "eabi"),
-    ];
+    let abis = [("x86_64-unknown-linux-gnux32", "x32"), ("arm-unknown-linux-gnueabi", "eabi")];
     for (target, abi) in abis {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_abi(abi), "{target} {abi}");
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 35670ba89e9..f283a625f97 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -356,7 +356,7 @@ impl<'test> TestCx<'test> {
             if proc_res.status.success() {
                 let err = &format!("{} test did not emit an error", self.config.mode);
                 let extra_note = (self.config.mode == crate::common::TestMode::Ui)
-                    .then_some("note: by default, ui tests are expected not to compile");
+                    .then_some("note: by default, ui tests are expected not to compile.\nhint: use check-pass, build-pass, or run-pass directive to change this behavior.");
                 self.fatal_proc_rec_general(err, extra_note, proc_res, || ());
             }
 
@@ -2567,6 +2567,11 @@ impl<'test> TestCx<'test> {
                 })
                 .into_owned();
 
+        // Normalize thread IDs in panic messages
+        normalized = static_regex!(r"thread '(?P<name>.*?)' \((rtid )?\d+\) panicked")
+            .replace_all(&normalized, "thread '$name' ($$TID) panicked")
+            .into_owned();
+
         normalized = normalized.replace("\t", "\\t"); // makes tabs visible
 
         // Remove test annotations like `//~ ERROR text` from the output,
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 8cf5873eab4..78181976df8 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-07b7dc90ee4df5815dbb91ef8e98cb93571230f5
+4c7749e8c8e50ad146da599eea3a250160c1bc2b
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index bcc3e9ec885..e6341252927 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -105,27 +105,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "or" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?;
             }
             "xor" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?;
             }
             "and" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?;
             }
             "nand" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?;
             }
             "xadd" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?;
             }
             "xsub" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?;
             }
             "min" => {
@@ -231,15 +231,14 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         let place = this.deref_pointer(place)?;
         let rhs = this.read_immediate(rhs)?;
 
-        if !place.layout.ty.is_integral() && !place.layout.ty.is_raw_ptr() {
+        if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr())
+            || !(rhs.layout.ty.is_integral() || rhs.layout.ty.is_raw_ptr())
+        {
             span_bug!(
                 this.cur_span(),
                 "atomic arithmetic operations only work on integer and raw pointer types",
             );
         }
-        if rhs.layout.ty != place.layout.ty {
-            span_bug!(this.cur_span(), "atomic arithmetic operation type mismatch");
-        }
 
         let old = match atomic_op {
             AtomicOp::Min =>
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 2b92c25a424..7d8538d24bb 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -11,7 +11,6 @@
 #![feature(variant_count)]
 #![feature(yeet_expr)]
 #![feature(nonzero_ops)]
-#![feature(strict_overflow_ops)]
 #![feature(pointer_is_aligned_to)]
 #![feature(ptr_metadata)]
 #![feature(unqualified_local_imports)]
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 73d671121f6..116f45f18dd 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -50,18 +50,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             // Some more operations are possible with atomics.
-            // The return value always has the provenance of the *left* operand.
+            // The RHS must be `usize`.
             Add | Sub | BitOr | BitAnd | BitXor => {
                 assert!(left.layout.ty.is_raw_ptr());
-                assert!(right.layout.ty.is_raw_ptr());
+                assert_eq!(right.layout.ty, this.tcx.types.usize);
                 let ptr = left.to_scalar().to_pointer(this)?;
                 // We do the actual operation with usize-typed scalars.
                 let left = ImmTy::from_uint(ptr.addr().bytes(), this.machine.layouts.usize);
-                let right = ImmTy::from_uint(
-                    right.to_scalar().to_target_usize(this)?,
-                    this.machine.layouts.usize,
-                );
-                let result = this.binary_op(bin_op, &left, &right)?;
+                let result = this.binary_op(bin_op, &left, right)?;
                 // Construct a new pointer with the provenance of `ptr` (the LHS).
                 let result_ptr = Pointer::new(
                     ptr.provenance,
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index 49c0c380a08..c2527bf8e25 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -62,7 +62,7 @@ impl<'tcx> MiriMachine<'tcx> {
             }
             "android" => {
                 Self::null_ptr_extern_statics(ecx, &["bsd_signal"])?;
-                Self::weak_symbol_extern_statics(ecx, &["signal", "getrandom"])?;
+                Self::weak_symbol_extern_statics(ecx, &["signal", "getrandom", "gettid"])?;
             }
             "windows" => {
                 // "_tls_used"
diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs
index 04c5d28838b..6cb0d221fc0 100644
--- a/src/tools/miri/src/shims/unix/android/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs
@@ -4,13 +4,14 @@ use rustc_span::Symbol;
 use rustc_target::callconv::FnAbi;
 
 use crate::shims::unix::android::thread::prctl;
+use crate::shims::unix::env::EvalContextExt as _;
 use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
 use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
 use crate::shims::unix::linux_like::syscall::syscall;
 use crate::*;
 
-pub fn is_dyn_sym(_name: &str) -> bool {
-    false
+pub fn is_dyn_sym(name: &str) -> bool {
+    matches!(name, "gettid")
 }
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -54,6 +55,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
             }
 
+            "gettid" => {
+                let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
+                let result = this.unix_gettid(link_name.as_str())?;
+                this.write_scalar(result, dest)?;
+            }
+
             // Dynamically invoked syscalls
             "syscall" => syscall(this, link_name, abi, args, dest)?,
 
diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
index 29c56ca81f7..a2a4be30eca 100644
--- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
+++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
@@ -11,7 +11,7 @@ note: inside `_::__rg_oom`
   --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
    |
 LL | #[alloc_error_handler]
-   | ---------------------- in this procedural macro expansion
+   | ---------------------- in this attribute macro expansion
 LL | fn alloc_error_handler(layout: Layout) -> ! {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr
index 9e6abf219f1..afabb8572bd 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/function_calls/exported_symbol_bad_unwind1.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/function_calls/exported_symbol_bad_unwind1.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
index 14b3be02a79..a1571173a53 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
@@ -1,10 +1,10 @@
 
-thread 'main' panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a function that cannot unwind
 stack backtrace:
 thread caused non-unwinding panic. aborting.
@@ -18,8 +18,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
 note: inside `nounwind`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
index 14b3be02a79..a1571173a53 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
@@ -1,10 +1,10 @@
 
-thread 'main' panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a function that cannot unwind
 stack backtrace:
 thread caused non-unwinding panic. aborting.
@@ -18,8 +18,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
 note: inside `nounwind`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
index 5a3d5b4a5eb..e755b262474 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
index 93720ca7d27..77dc2c61e26 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.stderr b/src/tools/miri/tests/fail/panic/abort_unwind.stderr
index 35052f37dfc..287f7d5432a 100644
--- a/src/tools/miri/tests/fail/panic/abort_unwind.stderr
+++ b/src/tools/miri/tests/fail/panic/abort_unwind.stderr
@@ -1,10 +1,10 @@
 
-thread 'main' panicked at tests/fail/panic/abort_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/abort_unwind.rs:LL:CC:
 PANIC!!!
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a function that cannot unwind
 stack backtrace:
 thread caused non-unwinding panic. aborting.
@@ -18,8 +18,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `std::panic::abort_unwind::<{closure@tests/fail/panic/abort_unwind.rs:LL:CC}, ()>` at RUSTLIB/core/src/panic.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
index b8404c4e457..b0a8492b6a6 100644
--- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr
+++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/panic/bad_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/bad_unwind.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 3f1fbfef721..b76ece7f1e5 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -1,14 +1,14 @@
 
-thread 'main' panicked at tests/fail/panic/double_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/double_panic.rs:LL:CC:
 first
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at tests/fail/panic/double_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/double_panic.rs:LL:CC:
 second
 stack backtrace:
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a destructor during cleanup
 thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
@@ -21,8 +21,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind_nobacktrace` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
index 9aca2ed654f..c469d24287f 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/panic/panic_abort1.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/panic_abort1.rs:LL:CC:
 panicking from libstd
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
@@ -17,8 +17,8 @@ LL | ABORT()
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> tests/fail/panic/panic_abort1.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
index 425817d5f86..bc7918f5f86 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/panic/panic_abort2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/panic_abort2.rs:LL:CC:
 42-panicking from libstd
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
@@ -17,8 +17,8 @@ LL | ABORT()
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> tests/fail/panic/panic_abort2.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
index a21e185219e..553bfa61635 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/panic/panic_abort3.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/panic_abort3.rs:LL:CC:
 panicking from libcore
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
@@ -17,8 +17,8 @@ LL | ABORT()
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> tests/fail/panic/panic_abort3.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
index a3cf5d72198..07ecab6661e 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/panic/panic_abort4.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/panic/panic_abort4.rs:LL:CC:
 42-panicking from libcore
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
@@ -17,8 +17,8 @@ LL | ABORT()
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> tests/fail/panic/panic_abort4.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr b/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr
index 1dcdb4a3996..ef87e7fe6db 100644
--- a/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr
@@ -1,5 +1,5 @@
 
-thread $NAME panicked at tests/fail/panic/tls_macro_const_drop_panic.rs:LL:CC:
+thread $NAME ($TID) panicked at tests/fail/panic/tls_macro_const_drop_panic.rs:LL:CC:
 ow
 fatal runtime error: thread local panicked on drop, aborting
 error: abnormal termination: the program aborted execution
diff --git a/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr b/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr
index 7e4907abd93..4fdaa97e1d0 100644
--- a/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr
@@ -1,5 +1,5 @@
 
-thread $NAME panicked at tests/fail/panic/tls_macro_drop_panic.rs:LL:CC:
+thread $NAME ($TID) panicked at tests/fail/panic/tls_macro_drop_panic.rs:LL:CC:
 ow
 fatal runtime error: thread local panicked on drop, aborting
 error: abnormal termination: the program aborted execution
diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
index 8295a581060..70f5d498da3 100644
--- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
+++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/fail/ptr_swap_nonoverlapping.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/ptr_swap_nonoverlapping.rs:LL:CC:
 unsafe precondition(s) violated: ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null and the specified memory ranges do not overlap
 
 This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.
@@ -16,8 +16,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> tests/fail/ptr_swap_nonoverlapping.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index f0f305d76bc..228e2d3de1f 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -1,12 +1,12 @@
 warning: You have explicitly enabled MIR optimizations, overriding Miri's default which is to completely disable them. Any optimizations may hide UB that Miri would otherwise detect, and it is not necessarily possible to predict what kind of UB will be missed. If you are enabling optimizations to make Miri run faster, we advise using cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR optimizations is usually marginal at best.
 
 
-thread 'main' panicked at tests/fail/terminate-terminator.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/terminate-terminator.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a function that cannot unwind
 stack backtrace:
 thread caused non-unwinding panic. aborting.
@@ -20,8 +20,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
 note: inside `has_cleanup`
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
index 216ae84512a..1c0f8cb7ec6 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -1,10 +1,10 @@
 
-thread 'main' panicked at tests/fail/unwind-action-terminate.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/fail/unwind-action-terminate.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 panic in a function that cannot unwind
 stack backtrace:
 thread caused non-unwinding panic. aborting.
@@ -18,8 +18,8 @@ LL | ABORT()
    = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
+   = note: inside `std::panicking::panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
    = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
 note: inside `panic_abort`
diff --git a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr
index 2be06968321..ad2bfc3f2a3 100644
--- a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr
+++ b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/alloc_error_handler_hook.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/alloc_error_handler_hook.rs:LL:CC:
 alloc error hook called
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr
index ddee4fd6ce3..7c2d089f952 100644
--- a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr
+++ b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at RUSTLIB/std/src/alloc.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/std/src/alloc.rs:LL:CC:
 memory allocation of 4 bytes failed
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/div-by-zero-2.stderr b/src/tools/miri/tests/panic/div-by-zero-2.stderr
index 4d4b0062d5e..013f3cd3c20 100644
--- a/src/tools/miri/tests/panic/div-by-zero-2.stderr
+++ b/src/tools/miri/tests/panic/div-by-zero-2.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/div-by-zero-2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/div-by-zero-2.rs:LL:CC:
 attempt to divide by zero
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr
index 8bcd635e8be..dad94377d12 100644
--- a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr
+++ b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr
@@ -1,11 +1,11 @@
 
-thread 'main' panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
 explicit panic
 
-thread 'main' panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/function_calls/exported_symbol_good_unwind.rs:LL:CC:
 explicit panic
diff --git a/src/tools/miri/tests/panic/mir-validation.rs b/src/tools/miri/tests/panic/mir-validation.rs
index e4b75cccbb5..b9097f2e8c5 100644
--- a/src/tools/miri/tests/panic/mir-validation.rs
+++ b/src/tools/miri/tests/panic/mir-validation.rs
@@ -8,6 +8,12 @@
 // Somehow on rustc Windows CI, the "Miri caused an ICE" message is not shown
 // and we don't even get a regular panic; rustc aborts with a different exit code instead.
 //@ignore-host: windows
+
+// FIXME: this tests a crash in rustc. For stage1, rustc is built with the downloaded standard
+// library which doesn't yet print the thread ID. Normalization can be removed at the stage bump.
+// For the grep: cfg(bootstrap)
+//@normalize-stderr-test: "thread 'rustc' panicked" -> "thread 'rustc' ($$TID) panicked"
+
 #![feature(custom_mir, core_intrinsics)]
 use core::intrinsics::mir::*;
 
diff --git a/src/tools/miri/tests/panic/mir-validation.stderr b/src/tools/miri/tests/panic/mir-validation.stderr
index f801ac907e6..1d40c93d709 100644
--- a/src/tools/miri/tests/panic/mir-validation.stderr
+++ b/src/tools/miri/tests/panic/mir-validation.stderr
@@ -6,7 +6,7 @@ LL |             *(tuple.0) = 1;
    |             ^^^^^^^^^^^^^^
 
 
-thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
+thread 'rustc' ($TID) panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
 Box<dyn Any>
 stack backtrace:
 
diff --git a/src/tools/miri/tests/panic/oob_subslice.stderr b/src/tools/miri/tests/panic/oob_subslice.stderr
index c0dabaff772..f8270f4ad4d 100644
--- a/src/tools/miri/tests/panic/oob_subslice.stderr
+++ b/src/tools/miri/tests/panic/oob_subslice.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/oob_subslice.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/oob_subslice.rs:LL:CC:
 range end index 5 out of range for slice of length 4
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr
index d674e2beb8d..8e618b978ef 100644
--- a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr
+++ b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/overflowing-lsh-neg.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/overflowing-lsh-neg.rs:LL:CC:
 attempt to shift left with overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr
index bb94f2e12c4..471bc849abb 100644
--- a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr
+++ b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/overflowing-rsh-1.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/overflowing-rsh-1.rs:LL:CC:
 attempt to shift right with overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr
index 0a29a57f3e1..94f5fb0f1ca 100644
--- a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr
+++ b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/overflowing-rsh-2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/overflowing-rsh-2.rs:LL:CC:
 attempt to shift right with overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/panic1.stderr b/src/tools/miri/tests/panic/panic1.stderr
index 130bc7737a4..ff7e287b5a5 100644
--- a/src/tools/miri/tests/panic/panic1.stderr
+++ b/src/tools/miri/tests/panic/panic1.stderr
@@ -1,8 +1,8 @@
 
-thread 'main' panicked at tests/panic/panic1.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/panic1.rs:LL:CC:
 panicking from libstd
 stack backtrace:
-   0: std::panicking::begin_panic_handler
+   0: std::panicking::panic_handler
  at RUSTLIB/std/src/panicking.rs:LL:CC
    1: std::rt::panic_fmt
  at RUSTLIB/core/src/panicking.rs:LL:CC
diff --git a/src/tools/miri/tests/panic/panic2.stderr b/src/tools/miri/tests/panic/panic2.stderr
index 157ffdb6b5d..c2e55178333 100644
--- a/src/tools/miri/tests/panic/panic2.stderr
+++ b/src/tools/miri/tests/panic/panic2.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/panic2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/panic2.rs:LL:CC:
 42-panicking from libstd
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/panic3.stderr b/src/tools/miri/tests/panic/panic3.stderr
index 529ef70870b..2fc761a4f3d 100644
--- a/src/tools/miri/tests/panic/panic3.stderr
+++ b/src/tools/miri/tests/panic/panic3.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/panic3.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/panic3.rs:LL:CC:
 panicking from libcore
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/panic4.stderr b/src/tools/miri/tests/panic/panic4.stderr
index ecd07dd7ded..f2f4c038000 100644
--- a/src/tools/miri/tests/panic/panic4.stderr
+++ b/src/tools/miri/tests/panic/panic4.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/panic4.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/panic4.rs:LL:CC:
 42-panicking from libcore
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/panic/transmute_fat2.stderr b/src/tools/miri/tests/panic/transmute_fat2.stderr
index 71e2d7a8208..8846c4c7fbc 100644
--- a/src/tools/miri/tests/panic/transmute_fat2.stderr
+++ b/src/tools/miri/tests/panic/transmute_fat2.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at tests/panic/transmute_fat2.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/panic/transmute_fat2.rs:LL:CC:
 index out of bounds: the len is 0 but the index is 0
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
diff --git a/src/tools/miri/tests/pass/panic/catch_panic.stderr b/src/tools/miri/tests/pass/panic/catch_panic.stderr
index bc745fca578..cd7384fb107 100644
--- a/src/tools/miri/tests/pass/panic/catch_panic.stderr
+++ b/src/tools/miri/tests/pass/panic/catch_panic.stderr
@@ -1,47 +1,47 @@
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Hello from std::panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 Caught panic message (&str): Hello from std::panic
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Hello from std::panic: 1
 Caught panic message (String): Hello from std::panic: 1
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Hello from std::panic_any: 2
 Caught panic message (String): Hello from std::panic_any: 2
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Box<dyn Any>
 Failed to get caught panic message.
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Hello from core::panic
 Caught panic message (&str): Hello from core::panic
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 Hello from core::panic: 5
 Caught panic message (String): Hello from core::panic: 5
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 index out of bounds: the len is 3 but the index is 4
 Caught panic message (String): index out of bounds: the len is 3 but the index is 4
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 attempt to divide by zero
 Caught panic message (&str): attempt to divide by zero
 
-thread 'main' panicked at RUSTLIB/core/src/ptr/const_ptr.rs:LL:CC:
+thread 'main' ($TID) panicked at RUSTLIB/core/src/ptr/const_ptr.rs:LL:CC:
 align_offset: align is not a power-of-two
 Caught panic message (&str): align_offset: align is not a power-of-two
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 assertion failed: false
 Caught panic message (&str): assertion failed: false
 
-thread 'main' panicked at tests/pass/panic/catch_panic.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/catch_panic.rs:LL:CC:
 assertion failed: false
 Caught panic message (&str): assertion failed: false
 Success!
diff --git a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr
index 4a3ac16debc..b388a3bedc0 100644
--- a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr
+++ b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr
@@ -1,7 +1,7 @@
 Thread 1 starting, will block on mutex
 Thread 1 reported it has started
 
-thread '<unnamed>' panicked at tests/pass/panic/concurrent-panic.rs:LL:CC:
+thread '<unnamed>' ($TID) panicked at tests/pass/panic/concurrent-panic.rs:LL:CC:
 panic in thread 2
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
@@ -9,7 +9,7 @@ Thread 2 blocking on thread 1
 Thread 2 reported it has started
 Unlocking mutex
 
-thread '<unnamed>' panicked at tests/pass/panic/concurrent-panic.rs:LL:CC:
+thread '<unnamed>' ($TID) panicked at tests/pass/panic/concurrent-panic.rs:LL:CC:
 panic in thread 1
 Thread 1 has exited
 Thread 2 has exited
diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr
index 8aff8f6ec55..7ae39204d4e 100644
--- a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr
+++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr
@@ -1,9 +1,9 @@
 
-thread 'main' panicked at tests/pass/panic/nested_panic_caught.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/nested_panic_caught.rs:LL:CC:
 once
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'main' panicked at tests/pass/panic/nested_panic_caught.rs:LL:CC:
+thread 'main' ($TID) panicked at tests/pass/panic/nested_panic_caught.rs:LL:CC:
 twice
 stack backtrace:
diff --git a/src/tools/miri/tests/pass/panic/thread_panic.stderr b/src/tools/miri/tests/pass/panic/thread_panic.stderr
index 3bb2991805c..92403d5152d 100644
--- a/src/tools/miri/tests/pass/panic/thread_panic.stderr
+++ b/src/tools/miri/tests/pass/panic/thread_panic.stderr
@@ -1,8 +1,8 @@
 
-thread '<unnamed>' panicked at tests/pass/panic/thread_panic.rs:LL:CC:
+thread '<unnamed>' ($TID) panicked at tests/pass/panic/thread_panic.rs:LL:CC:
 Hello!
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 
-thread 'childthread' panicked at tests/pass/panic/thread_panic.rs:LL:CC:
+thread 'childthread' ($TID) panicked at tests/pass/panic/thread_panic.rs:LL:CC:
 Hello, world!
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 73fbe2cc020..f021d5194cd 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -248,7 +248,8 @@ regexes! {
     // erase alloc ids
     "alloc[0-9]+"                    => "ALLOC",
     // erase thread ids
-    r"unnamed-[0-9]+"               => "unnamed-ID",
+    r"unnamed-[0-9]+"                => "unnamed-ID",
+    r"thread '(?P<name>.*?)' \(\d+\) panicked" => "thread '$name' ($$TID) panicked",
     // erase borrow tags
     "<[0-9]+>"                       => "<TAG>",
     "<[0-9]+="                       => "<TAG=",
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index ee48e373366..739eff72f05 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -23,6 +23,7 @@ pub struct Diff {
     actual: Option<String>,
     actual_name: Option<String>,
     normalizers: Vec<(String, String)>,
+    bless_dir: Option<String>,
     drop_bomb: DropBomb,
 }
 
@@ -37,6 +38,7 @@ impl Diff {
             actual: None,
             actual_name: None,
             normalizers: Vec::new(),
+            bless_dir: std::env::var("RUSTC_BLESS_TEST").ok(),
             drop_bomb: DropBomb::arm("diff"),
         }
     }
@@ -44,6 +46,13 @@ impl Diff {
     /// Specify the expected output for the diff from a file.
     pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
+        // In `--bless` mode, create the snapshot file if it doesn't already exist.
+        // The empty file will be overwritten with the actual text.
+        if self.bless_dir.is_some()
+            && let Ok(false) = std::fs::exists(path)
+        {
+            fs::write(path, "");
+        }
         let content = fs::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
@@ -148,7 +157,7 @@ impl Diff {
         let Some(ref expected_file) = self.expected_file else {
             return false;
         };
-        let Ok(bless_dir) = std::env::var("RUSTC_BLESS_TEST") else {
+        let Some(ref bless_dir) = self.bless_dir else {
             return false;
         };
 
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 ac7392641c0..5c980068e4b 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
@@ -1,15 +1,23 @@
-use crate::{is_win7, is_windows, is_windows_msvc, uname};
+use crate::{is_arm64ec, is_win7, is_windows, is_windows_msvc, uname};
+
+fn get_windows_msvc_libs() -> Vec<&'static str> {
+    let mut libs =
+        vec!["ws2_32.lib", "userenv.lib", "bcrypt.lib", "ntdll.lib", "synchronization.lib"];
+    if is_win7() {
+        libs.push("advapi32.lib");
+    }
+    libs
+}
 
 /// `EXTRACFLAGS`
 pub fn extra_c_flags() -> Vec<&'static str> {
     if is_windows() {
         if is_windows_msvc() {
-            let mut libs =
-                vec!["ws2_32.lib", "userenv.lib", "bcrypt.lib", "ntdll.lib", "synchronization.lib"];
-            if is_win7() {
-                libs.push("advapi32.lib");
+            let mut args = get_windows_msvc_libs();
+            if is_arm64ec() {
+                args.push("/arm64EC");
             }
-            libs
+            args
         } else {
             vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"]
         }
@@ -26,6 +34,18 @@ pub fn extra_c_flags() -> Vec<&'static str> {
     }
 }
 
+pub fn extra_linker_flags() -> Vec<&'static str> {
+    if is_windows_msvc() {
+        let mut args = get_windows_msvc_libs();
+        if is_arm64ec() {
+            args.push("/MACHINE:ARM64EC");
+        }
+        args
+    } else {
+        vec![]
+    }
+}
+
 /// `EXTRACXXFLAGS`
 pub fn extra_cxx_flags() -> Vec<&'static str> {
     if is_windows() {
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index b7d89b130c6..191e205f257 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -56,7 +56,7 @@ pub use crate::external_deps::c_build::{
 };
 // Re-exports of external dependencies.
 pub use crate::external_deps::c_cxx_compiler::{
-    Cc, Gcc, cc, cxx, extra_c_flags, extra_cxx_flags, gcc,
+    Cc, Gcc, cc, cxx, extra_c_flags, extra_cxx_flags, extra_linker_flags, gcc,
 };
 pub use crate::external_deps::cargo::cargo;
 pub use crate::external_deps::clang::{Clang, clang};
@@ -84,6 +84,6 @@ pub use crate::string::{
 };
 // Helpers for checking target information.
 pub use crate::targets::{
-    apple_os, is_aix, is_darwin, is_win7, is_windows, is_windows_gnu, is_windows_msvc,
+    apple_os, is_aix, is_arm64ec, is_darwin, is_win7, is_windows, is_windows_gnu, is_windows_msvc,
     llvm_components_contain, target, uname,
 };
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
index b20e12561fb..6288f5f7c59 100644
--- a/src/tools/run-make-support/src/targets.rs
+++ b/src/tools/run-make-support/src/targets.rs
@@ -46,6 +46,12 @@ pub fn is_aix() -> bool {
     target().contains("aix")
 }
 
+/// Check if target is arm64ec.
+#[must_use]
+pub fn is_arm64ec() -> bool {
+    target().starts_with("arm64ec")
+}
+
 /// Get the target OS on Apple operating systems.
 #[must_use]
 pub fn apple_os() -> &'static str {
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 f9eb44d03ab..14bc380586a 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
@@ -10706,20 +10706,6 @@ The tracking issue for this feature is: [#77998]
         deny_since: None,
     },
     Lint {
-        label: "strict_overflow_ops",
-        description: r##"# `strict_overflow_ops`
-
-The tracking issue for this feature is: [#118260]
-
-[#118260]: https://github.com/rust-lang/rust/issues/118260
-
-------------------------
-"##,
-        default_severity: Severity::Allow,
-        warn_since: None,
-        deny_since: None,
-    },
-    Lint {
         label: "strict_provenance_atomic_ptr",
         description: r##"# `strict_provenance_atomic_ptr`
 
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index a9f58b9328e..4a9399377d1 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -185,10 +185,11 @@ fn dont_emit_ICE() {
         "tests/target/issue-6105.rs",
     ];
 
+    let panic_re = regex::Regex::new("thread.*panicked").unwrap();
     for file in files {
         let args = [file];
         let (_stdout, stderr) = rustfmt(&args);
-        assert!(!stderr.contains("thread 'main' panicked"));
+        assert!(!panic_re.is_match(&stderr));
     }
 }