about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2024-12-11 11:49:08 +0200
committerLaurențiu Nicola <lnicola@dend.ro>2024-12-11 11:49:08 +0200
commit5db2aa865cdc4bf0634fdcbdd8d201253938f02a (patch)
tree6ba3b87d4ac3b10b67159211a493f785c76ee0fa /src
parent1649eb6dd74507bbd9513464609fcd5a9bcc655b (diff)
parent5a6036a1802262f8cf02192b02026688d396f1d7 (diff)
downloadrust-5db2aa865cdc4bf0634fdcbdd8d201253938f02a.tar.gz
rust-5db2aa865cdc4bf0634fdcbdd8d201253938f02a.zip
Merge from rust-lang/rust
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/Cargo.lock8
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bootstrap.py664
-rw-r--r--src/bootstrap/bootstrap_test.py42
-rwxr-xr-xsrc/bootstrap/configure.py519
-rw-r--r--src/bootstrap/mk/Makefile.in8
-rw-r--r--src/bootstrap/src/bin/main.rs22
-rw-r--r--src/bootstrap/src/bin/rustc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/clean.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs12
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs30
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs13
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs25
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs57
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs59
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs14
-rw-r--r--src/bootstrap/src/core/builder/mod.rs121
-rw-r--r--src/bootstrap/src/core/builder/tests.rs46
-rw-r--r--src/bootstrap/src/core/config/config.rs164
-rw-r--r--src/bootstrap/src/core/config/flags.rs4
-rw-r--r--src/bootstrap/src/core/download.rs33
-rw-r--r--src/bootstrap/src/core/sanity.rs26
-rw-r--r--src/bootstrap/src/lib.rs83
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/helpers.rs8
-rw-r--r--src/bootstrap/src/utils/job.rs41
-rw-r--r--src/bootstrap/src/utils/metrics.rs9
-rw-r--r--src/bootstrap/src/utils/render_tests.rs50
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rwxr-xr-xsrc/ci/cpu-usage-over-time.py36
-rw-r--r--src/ci/docker/host-aarch64/dist-arm-linux/Dockerfile (renamed from src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile)2
-rw-r--r--src/ci/docker/host-aarch64/dist-arm-linux/arm-linux-gnueabi.defconfig (renamed from src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig)0
-rw-r--r--src/ci/docker/host-x86_64/arm-android/Dockerfile5
-rw-r--r--src/ci/docker/host-x86_64/dist-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-ohos/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile9
-rwxr-xr-xsrc/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py149
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/run.sh35
-rw-r--r--src/ci/docker/scripts/android-base-apt-get.sh2
-rwxr-xr-xsrc/ci/docker/scripts/android-sdk-manager.py60
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py8
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh4
-rwxr-xr-xsrc/ci/github-actions/calculate-job-matrix.py13
-rw-r--r--src/ci/github-actions/jobs.yml80
-rw-r--r--src/ci/scripts/upload-build-metrics.py21
-rw-r--r--src/ci/shared.sh3
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/platform-support.md16
-rw-r--r--src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md2
-rw-r--r--src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md16
-rw-r--r--src/doc/rustdoc/src/unstable-features.md4
-rw-r--r--src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md7
-rw-r--r--src/doc/unstable-book/src/compiler-flags/randomize-layout.md23
-rw-r--r--src/doc/unstable-book/src/compiler-flags/reg-struct-return.md15
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md6
-rw-r--r--src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md10
-rwxr-xr-xsrc/etc/dec2flt_table.py46
-rw-r--r--src/etc/gdb_load_rust_pretty_printers.py1
-rw-r--r--src/etc/gdb_lookup.py7
-rw-r--r--src/etc/gdb_providers.py35
-rwxr-xr-xsrc/etc/generate-deriving-span-tests.py62
-rwxr-xr-xsrc/etc/generate-keyword-tests.py8
-rwxr-xr-xsrc/etc/htmldocck.py260
-rw-r--r--src/etc/lldb_batchmode.py69
-rw-r--r--src/etc/lldb_commands23
-rw-r--r--src/etc/lldb_providers.py186
-rw-r--r--src/etc/rust_analyzer_settings.json3
-rw-r--r--src/etc/rust_types.py3
-rw-r--r--src/librustdoc/clean/auto_trait.rs3
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs13
-rw-r--r--src/librustdoc/core.rs14
-rw-r--r--src/librustdoc/doctest.rs22
-rw-r--r--src/librustdoc/formats/renderer.rs97
-rw-r--r--src/librustdoc/html/markdown.rs225
-rw-r--r--src/librustdoc/html/markdown/footnotes.rs25
-rw-r--r--src/librustdoc/html/render/context.rs122
-rw-r--r--src/librustdoc/html/render/mod.rs107
-rw-r--r--src/librustdoc/html/render/print_item.rs119
-rw-r--r--src/librustdoc/html/render/sidebar.rs72
-rw-r--r--src/librustdoc/html/render/write_shared.rs25
-rw-r--r--src/librustdoc/html/sources.rs60
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css83
-rw-r--r--src/librustdoc/json/conversions.rs29
-rw-r--r--src/librustdoc/json/mod.rs10
-rw-r--r--src/librustdoc/lib.rs40
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs11
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs3
-rw-r--r--src/librustdoc/scrape_examples.rs5
m---------src/llvm-project0
-rw-r--r--src/rustdoc-json-types/lib.rs18
-rw-r--r--src/stage0900
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md50
-rw-r--r--src/tools/clippy/Cargo.toml6
-rw-r--r--src/tools/clippy/book/src/SUMMARY.md1
-rw-r--r--src/tools/clippy/book/src/attribs.md53
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md4
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md2
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml6
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs6
-rw-r--r--src/tools/clippy/clippy_config/src/lib.rs8
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs15
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml1
-rw-r--r--src/tools/clippy/clippy_dev/src/dogfood.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs62
-rw-r--r--src/tools/clippy/clippy_dev/src/lint.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs44
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs25
-rw-r--r--src/tools/clippy/clippy_dev/src/release.rs27
-rw-r--r--src/tools/clippy/clippy_dev/src/sync.rs33
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs71
-rw-r--r--src/tools/clippy/clippy_dev/src/utils.rs142
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_range.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs67
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_mutex.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/incompatible_msrv.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/init_numbered_fields.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_bits.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_div_ceil.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_float_methods.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_hash_one.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/err_expect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_update.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_async_block.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_field_names.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/string_patterns.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_trait_names.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/zombie_processes.rs2
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml13
-rw-r--r--src/tools/clippy/clippy_utils/README.md40
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs29
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs44
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_origin.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs (renamed from src/tools/clippy/clippy_config/src/msrvs.rs)2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs19
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs4
-rw-r--r--src/tools/clippy/rust-toolchain4
-rw-r--r--src/tools/clippy/src/driver.rs8
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.rs7
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.stderr17
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed295
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr60
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed40
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs40
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr17
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_lifetimes.rs7
-rw-r--r--src/tools/clippy/tests/ui/fn_address_comparisons.rs23
-rw-r--r--src/tools/clippy/tests/ui/fn_address_comparisons.stderr17
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.rs29
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.stderr65
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.rs18
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.stderr51
-rw-r--r--src/tools/clippy/tests/ui/if_let_mutex.edition2021.stderr (renamed from src/tools/clippy/tests/ui/if_let_mutex.stderr)8
-rw-r--r--src/tools/clippy/tests/ui/if_let_mutex.rs11
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed6
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs6
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr24
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_crate.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.fixed15
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.rs11
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.stderr86
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr140
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed18
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs18
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr8
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed21
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs21
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.stderr50
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.fixed22
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.rs20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.stderr60
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.1.fixed35
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.2.fixed35
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.rs35
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.stderr60
-rw-r--r--src/tools/compiletest/src/common.rs22
-rw-r--r--src/tools/compiletest/src/compute_diff.rs2
-rw-r--r--src/tools/compiletest/src/debuggers.rs6
-rw-r--r--src/tools/compiletest/src/directive-list.rs3
-rw-r--r--src/tools/compiletest/src/header.rs13
-rw-r--r--src/tools/compiletest/src/header/auxiliary.rs11
-rw-r--r--src/tools/compiletest/src/header/needs.rs51
-rw-r--r--src/tools/compiletest/src/header/tests.rs37
-rw-r--r--src/tools/compiletest/src/lib.rs27
-rw-r--r--src/tools/compiletest/src/runtest.rs284
-rw-r--r--src/tools/compiletest/src/runtest/codegen_units.rs22
-rw-r--r--src/tools/compiletest/src/runtest/coverage.rs16
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs10
-rw-r--r--src/tools/compiletest/src/runtest/incremental.rs2
-rw-r--r--src/tools/compiletest/src/runtest/mir_opt.rs2
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc_json.rs2
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs6
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/jsondocck/src/cache.rs5
-rw-r--r--src/tools/jsondocck/src/error.rs28
-rw-r--r--src/tools/jsondocck/src/main.rs398
-rw-r--r--src/tools/miri/Cargo.lock53
-rw-r--r--src/tools/miri/Cargo.toml5
-rw-r--r--src/tools/miri/README.md7
-rw-r--r--src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock7
-rw-r--r--src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml8
-rw-r--r--src/tools/miri/bench-cargo-miri/string-replace/data.json1
-rw-r--r--src/tools/miri/bench-cargo-miri/string-replace/src/main.rs7
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs13
-rwxr-xr-xsrc/tools/miri/ci/ci.sh6
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs10
-rw-r--r--src/tools/miri/src/bin/miri.rs6
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs108
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs14
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs61
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs190
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs27
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs238
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs25
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs17
-rw-r--r--src/tools/miri/src/machine.rs10
-rw-r--r--src/tools/miri/src/shims/backtrace.rs10
-rw-r--r--src/tools/miri/src/shims/files.rs411
-rw-r--r--src/tools/miri/src/shims/io_error.rs69
-rw-r--r--src/tools/miri/src/shims/mod.rs4
-rw-r--r--src/tools/miri/src/shims/native_lib.rs46
-rw-r--r--src/tools/miri/src/shims/panic.rs5
-rw-r--r--src/tools/miri/src/shims/unix/android/foreign_items.rs29
-rw-r--r--src/tools/miri/src/shims/unix/fd.rs406
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs117
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs173
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs13
-rw-r--r--src/tools/miri/src/shims/unix/linux/mod.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/epoll.rs (renamed from src/tools/miri/src/shims/unix/linux/epoll.rs)14
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/eventfd.rs (renamed from src/tools/miri/src/shims/unix/linux/eventfd.rs)55
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/mod.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/sync.rs (renamed from src/tools/miri/src/shims/unix/linux/sync.rs)0
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/syscall.rs (renamed from src/tools/miri/src/shims/unix/linux/syscall.rs)4
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/mod.rs7
-rw-r--r--src/tools/miri/src/shims/unix/solarish/foreign_items.rs28
-rw-r--r--src/tools/miri/src/shims/unix/unnamed_socket.rs236
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs3
-rw-r--r--src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs9
-rw-r--r--src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs9
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs2
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs32
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr14
-rw-r--r--src/tools/miri/tests/fail/breakpoint.rs4
-rw-r--r--src/tools/miri/tests/fail/breakpoint.stderr4
-rw-r--r--src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs27
-rw-r--r--src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr15
-rw-r--r--src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.rs87
-rw-r--r--src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr20
-rw-r--r--src/tools/miri/tests/native-lib/pass/ptr_read_access.rs27
-rw-r--r--src/tools/miri/tests/native-lib/pass/ptr_write_access.rs202
-rw-r--r--src/tools/miri/tests/native-lib/ptr_read_access.c8
-rw-r--r--src/tools/miri/tests/native-lib/ptr_write_access.c90
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs2
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs2
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs9
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs7
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs4
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-mem.rs10
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs16
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs19
-rw-r--r--src/tools/miri/tests/pass/0weak_memory_consistency.rs177
-rw-r--r--src/tools/miri/tests/pass/async-closure-captures.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure-drop.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure.rs2
-rw-r--r--src/tools/miri/tests/pass/async-drop.rs2
-rw-r--r--src/tools/miri/tests/pass/async-fn.rs1
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs69
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr18
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout5
-rw-r--r--src/tools/miri/tests/pass/dyn-star.rs1
-rw-r--r--src/tools/miri/tests/pass/function_pointers.rs2
-rw-r--r--src/tools/miri/tests/pass/future-self-referential.rs1
-rw-r--r--src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs91
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs22
-rw-r--r--src/tools/miri/tests/pass/issues/issue-91636.rs2
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-2068.rs2
-rw-r--r--src/tools/miri/tests/pass/move-data-across-await-point.rs1
-rw-r--r--src/tools/miri/tests/pass/shims/fs.rs7
-rw-r--r--src/tools/miri/tests/ui.rs1
-rw-r--r--src/tools/nix-dev-shell/envrc-flake2
-rw-r--r--src/tools/nix-dev-shell/envrc-shell2
-rw-r--r--src/tools/nix-dev-shell/flake.nix5
-rw-r--r--src/tools/nix-dev-shell/shell.nix5
-rwxr-xr-xsrc/tools/publish_toolstate.py226
-rw-r--r--src/tools/run-make-support/Cargo.toml2
-rw-r--r--src/tools/run-make-support/src/command.rs2
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs13
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/memory_usage.rs4
-rw-r--r--src/tools/rustbook/Cargo.lock486
-rw-r--r--src/tools/rustbook/Cargo.toml3
-rw-r--r--src/tools/rustbook/src/main.rs11
-rw-r--r--src/tools/rustfmt/src/parse/session.rs29
-rw-r--r--src/tools/rustfmt/src/patterns.rs6
-rw-r--r--src/tools/rustfmt/tests/target/guard_patterns.rs12
-rw-r--r--src/tools/tidy/config/black.toml18
-rw-r--r--src/tools/tidy/config/requirements.in1
-rw-r--r--src/tools/tidy/config/requirements.txt52
-rw-r--r--src/tools/tidy/config/ruff.toml6
-rw-r--r--src/tools/tidy/src/deps.rs8
-rw-r--r--src/tools/tidy/src/ext_tool_checks.rs30
-rw-r--r--src/tools/tidy/src/fluent_period.rs1
-rw-r--r--src/tools/tidy/src/issues.txt14
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--src/tools/unicode-table-generator/src/range_search.rs1
-rw-r--r--src/tools/unicode-table-generator/src/raw_emitter.rs4
-rw-r--r--src/tools/wasm-component-ld/Cargo.toml2
464 files changed, 8576 insertions, 5180 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 86d23d9bd02..c9697e670b7 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -324,9 +324,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.162"
+version = "0.2.167"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
 
 [[package]]
 name = "libredox"
@@ -558,9 +558,9 @@ dependencies = [
 
 [[package]]
 name = "sysinfo"
-version = "0.31.4"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
+checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46"
 dependencies = [
  "core-foundation-sys",
  "libc",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index fcd97b7b589..6da716b7a89 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -63,7 +63,7 @@ walkdir = "2.4"
 xz2 = "0.1"
 
 # Dependencies needed by the build-metrics feature
-sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] }
+sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] }
 
 [target.'cfg(windows)'.dependencies.junction]
 version = "1.0.0"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d7ae0299dd6..89415afbe3b 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -19,14 +19,17 @@ try:
 except ImportError:
     lzma = None
 
+
 def platform_is_win32():
-    return sys.platform == 'win32'
+    return sys.platform == "win32"
+
 
 if platform_is_win32():
     EXE_SUFFIX = ".exe"
 else:
     EXE_SUFFIX = ""
 
+
 def get_cpus():
     if hasattr(os, "sched_getaffinity"):
         return len(os.sched_getaffinity(0))
@@ -51,11 +54,14 @@ def get(base, url, path, checksums, verbose=False):
 
     try:
         if url not in checksums:
-            raise RuntimeError(("src/stage0 doesn't contain a checksum for {}. "
-                                "Pre-built artifacts might not be available for this "
-                                "target at this time, see https://doc.rust-lang.org/nightly"
-                                "/rustc/platform-support.html for more information.")
-                                .format(url))
+            raise RuntimeError(
+                (
+                    "src/stage0 doesn't contain a checksum for {}. "
+                    "Pre-built artifacts might not be available for this "
+                    "target at this time, see https://doc.rust-lang.org/nightly"
+                    "/rustc/platform-support.html for more information."
+                ).format(url)
+            )
         sha256 = checksums[url]
         if os.path.exists(path):
             if verify(path, sha256, False):
@@ -64,8 +70,11 @@ def get(base, url, path, checksums, verbose=False):
                 return
             else:
                 if verbose:
-                    eprint("ignoring already-download file",
-                        path, "due to failed verification")
+                    eprint(
+                        "ignoring already-download file",
+                        path,
+                        "due to failed verification",
+                    )
                 os.unlink(path)
         download(temp_path, "{}/{}".format(base, url), True, verbose)
         if not verify(temp_path, sha256, verbose):
@@ -79,12 +88,14 @@ def get(base, url, path, checksums, verbose=False):
                 eprint("removing", temp_path)
             os.unlink(temp_path)
 
+
 def curl_version():
     m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"]))
     if m is None:
         return (0, 0)
     return (int(m[1]), int(m[2]))
 
+
 def download(path, url, probably_big, verbose):
     for _ in range(4):
         try:
@@ -114,32 +125,53 @@ def _download(path, url, probably_big, verbose, exception):
         require(["curl", "--version"], exception=platform_is_win32())
         extra_flags = []
         if curl_version() > (7, 70):
-            extra_flags = [ "--retry-all-errors" ]
+            extra_flags = ["--retry-all-errors"]
         # options should be kept in sync with
         # src/bootstrap/src/core/download.rs
         # for consistency.
         # they are also more compreprensivly explained in that file.
-        run(["curl", option] + extra_flags + [
-            # Follow redirect.
-            "--location",
-            # timeout if speed is < 10 bytes/sec for > 30 seconds
-            "--speed-time", "30", "--speed-limit", "10",
-            # timeout if cannot connect within 30 seconds
-            "--connect-timeout", "30",
-            "--output", path,
-            "--continue-at", "-",
-            "--retry", "3", "--show-error", "--remote-time", "--fail", url],
+        run(
+            ["curl", option]
+            + extra_flags
+            + [
+                # Follow redirect.
+                "--location",
+                # timeout if speed is < 10 bytes/sec for > 30 seconds
+                "--speed-time",
+                "30",
+                "--speed-limit",
+                "10",
+                # timeout if cannot connect within 30 seconds
+                "--connect-timeout",
+                "30",
+                "--output",
+                path,
+                "--continue-at",
+                "-",
+                "--retry",
+                "3",
+                "--show-error",
+                "--remote-time",
+                "--fail",
+                url,
+            ],
             verbose=verbose,
-            exception=True, # Will raise RuntimeError on failure
+            exception=True,  # Will raise RuntimeError on failure
         )
     except (subprocess.CalledProcessError, OSError, RuntimeError):
         # see http://serverfault.com/questions/301128/how-to-download
+        script = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;"
         if platform_is_win32():
-            run_powershell([
-                 "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
-                 "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
+            run_powershell(
+                [
+                    script,
+                    "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(
+                        url, path
+                    ),
+                ],
                 verbose=verbose,
-                exception=exception)
+                exception=exception,
+            )
         # Check if the RuntimeError raised by run(curl) should be silenced
         elif verbose or exception:
             raise
@@ -153,9 +185,11 @@ def verify(path, expected, verbose):
         found = hashlib.sha256(source.read()).hexdigest()
     verified = found == expected
     if not verified:
-        eprint("invalid checksum:\n"
-              "    found:    {}\n"
-              "    expected: {}".format(found, expected))
+        eprint(
+            "invalid checksum:\n" "    found:    {}\n" "    expected: {}".format(
+                found, expected
+            )
+        )
     return verified
 
 
@@ -170,7 +204,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
             name = member.replace(fname + "/", "", 1)
             if match is not None and not name.startswith(match):
                 continue
-            name = name[len(match) + 1:]
+            name = name[len(match) + 1 :]
 
             dst_path = os.path.join(dst, name)
             if verbose:
@@ -186,18 +220,18 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
 def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
     """Run a child program in a new process"""
     if verbose:
-        eprint("running: " + ' '.join(args))
+        eprint("running: " + " ".join(args))
     sys.stdout.flush()
     # Ensure that the .exe is used on Windows just in case a Linux ELF has been
     # compiled in the same directory.
-    if os.name == 'nt' and not args[0].endswith('.exe'):
-        args[0] += '.exe'
+    if os.name == "nt" and not args[0].endswith(".exe"):
+        args[0] += ".exe"
     # Use Popen here instead of call() as it apparently allows powershell on
     # Windows to not lock up waiting for input presumably.
     ret = subprocess.Popen(args, **kwargs)
     code = ret.wait()
     if code != 0:
-        err = "failed to run: " + ' '.join(args)
+        err = "failed to run: " + " ".join(args)
         if verbose or exception:
             raise RuntimeError(err)
         # For most failures, we definitely do want to print this error, or the user will have no
@@ -209,30 +243,30 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
         else:
             sys.exit(err)
 
+
 def run_powershell(script, *args, **kwargs):
     """Run a powershell script"""
     run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs)
 
 
 def require(cmd, exit=True, exception=False):
-    '''Run a command, returning its output.
+    """Run a command, returning its output.
     On error,
         If `exception` is `True`, raise the error
         Otherwise If `exit` is `True`, exit the process
-        Else return None.'''
+        Else return None."""
     try:
         return subprocess.check_output(cmd).strip()
     except (subprocess.CalledProcessError, OSError) as exc:
         if exception:
             raise
         elif exit:
-            eprint("ERROR: unable to run `{}`: {}".format(' '.join(cmd), exc))
+            eprint("ERROR: unable to run `{}`: {}".format(" ".join(cmd), exc))
             eprint("Please make sure it's installed and in the path.")
             sys.exit(1)
         return None
 
 
-
 def format_build_time(duration):
     """Return a nicer format for build time
 
@@ -252,13 +286,16 @@ def default_build_triple(verbose):
 
     if platform_is_win32():
         try:
-            version = subprocess.check_output(["rustc", "--version", "--verbose"],
-                    stderr=subprocess.DEVNULL)
+            version = subprocess.check_output(
+                ["rustc", "--version", "--verbose"], stderr=subprocess.DEVNULL
+            )
             version = version.decode(default_encoding)
-            host = next(x for x in version.split('\n') if x.startswith("host: "))
+            host = next(x for x in version.split("\n") if x.startswith("host: "))
             triple = host.split("host: ")[1]
             if verbose:
-                eprint("detected default triple {} from pre-installed rustc".format(triple))
+                eprint(
+                    "detected default triple {} from pre-installed rustc".format(triple)
+                )
             return triple
         except Exception as e:
             if verbose:
@@ -270,148 +307,149 @@ def default_build_triple(verbose):
 
     # If we do not have `uname`, assume Windows.
     if uname is None:
-        return 'x86_64-pc-windows-msvc'
+        return "x86_64-pc-windows-msvc"
 
     kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2)
 
     # The goal here is to come up with the same triple as LLVM would,
     # at least for the subset of platforms we're willing to target.
     kerneltype_mapper = {
-        'Darwin': 'apple-darwin',
-        'DragonFly': 'unknown-dragonfly',
-        'FreeBSD': 'unknown-freebsd',
-        'Haiku': 'unknown-haiku',
-        'NetBSD': 'unknown-netbsd',
-        'OpenBSD': 'unknown-openbsd',
-        'GNU': 'unknown-hurd',
+        "Darwin": "apple-darwin",
+        "DragonFly": "unknown-dragonfly",
+        "FreeBSD": "unknown-freebsd",
+        "Haiku": "unknown-haiku",
+        "NetBSD": "unknown-netbsd",
+        "OpenBSD": "unknown-openbsd",
+        "GNU": "unknown-hurd",
     }
 
     # Consider the direct transformation first and then the special cases
     if kernel in kerneltype_mapper:
         kernel = kerneltype_mapper[kernel]
-    elif kernel == 'Linux':
+    elif kernel == "Linux":
         # Apple doesn't support `-o` so this can't be used in the combined
         # uname invocation above
         ostype = require(["uname", "-o"], exit=required).decode(default_encoding)
-        if ostype == 'Android':
-            kernel = 'linux-android'
+        if ostype == "Android":
+            kernel = "linux-android"
         else:
-            kernel = 'unknown-linux-gnu'
-    elif kernel == 'SunOS':
-        kernel = 'pc-solaris'
+            kernel = "unknown-linux-gnu"
+    elif kernel == "SunOS":
+        kernel = "pc-solaris"
         # On Solaris, uname -m will return a machine classification instead
         # of a cpu type, so uname -p is recommended instead.  However, the
         # output from that option is too generic for our purposes (it will
         # always emit 'i386' on x86/amd64 systems).  As such, isainfo -k
         # must be used instead.
-        cputype = require(['isainfo', '-k']).decode(default_encoding)
+        cputype = require(["isainfo", "-k"]).decode(default_encoding)
         # sparc cpus have sun as a target vendor
-        if 'sparc' in cputype:
-            kernel = 'sun-solaris'
-    elif kernel.startswith('MINGW'):
+        if "sparc" in cputype:
+            kernel = "sun-solaris"
+    elif kernel.startswith("MINGW"):
         # msys' `uname` does not print gcc configuration, but prints msys
         # configuration. so we cannot believe `uname -m`:
         # msys1 is always i686 and msys2 is always x86_64.
         # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
         # MINGW64 on x86_64.
-        kernel = 'pc-windows-gnu'
-        cputype = 'i686'
-        if os.environ.get('MSYSTEM') == 'MINGW64':
-            cputype = 'x86_64'
-    elif kernel.startswith('MSYS'):
-        kernel = 'pc-windows-gnu'
-    elif kernel.startswith('CYGWIN_NT'):
-        cputype = 'i686'
-        if kernel.endswith('WOW64'):
-            cputype = 'x86_64'
-        kernel = 'pc-windows-gnu'
+        kernel = "pc-windows-gnu"
+        cputype = "i686"
+        if os.environ.get("MSYSTEM") == "MINGW64":
+            cputype = "x86_64"
+    elif kernel.startswith("MSYS"):
+        kernel = "pc-windows-gnu"
+    elif kernel.startswith("CYGWIN_NT"):
+        cputype = "i686"
+        if kernel.endswith("WOW64"):
+            cputype = "x86_64"
+        kernel = "pc-windows-gnu"
     elif platform_is_win32():
         # Some Windows platforms might have a `uname` command that returns a
         # non-standard string (e.g. gnuwin32 tools returns `windows32`). In
         # these cases, fall back to using sys.platform.
-        return 'x86_64-pc-windows-msvc'
-    elif kernel == 'AIX':
+        return "x86_64-pc-windows-msvc"
+    elif kernel == "AIX":
         # `uname -m` returns the machine ID rather than machine hardware on AIX,
         # so we are unable to use cputype to form triple. AIX 7.2 and
         # above supports 32-bit and 64-bit mode simultaneously and `uname -p`
         # returns `powerpc`, however we only supports `powerpc64-ibm-aix` in
         # rust on AIX. For above reasons, kerneltype_mapper and cputype_mapper
         # are not used to infer AIX's triple.
-        return 'powerpc64-ibm-aix'
+        return "powerpc64-ibm-aix"
     else:
         err = "unknown OS type: {}".format(kernel)
         sys.exit(err)
 
-    if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd':
-        cputype = subprocess.check_output(
-              ['uname', '-p']).strip().decode(default_encoding)
+    if cputype in ["powerpc", "riscv"] and kernel == "unknown-freebsd":
+        cputype = (
+            subprocess.check_output(["uname", "-p"]).strip().decode(default_encoding)
+        )
     cputype_mapper = {
-        'BePC': 'i686',
-        'aarch64': 'aarch64',
-        'aarch64eb': 'aarch64',
-        'amd64': 'x86_64',
-        'arm64': 'aarch64',
-        'i386': 'i686',
-        'i486': 'i686',
-        'i686': 'i686',
-        'i686-AT386': 'i686',
-        'i786': 'i686',
-        'loongarch64': 'loongarch64',
-        'm68k': 'm68k',
-        'csky': 'csky',
-        'powerpc': 'powerpc',
-        'powerpc64': 'powerpc64',
-        'powerpc64le': 'powerpc64le',
-        'ppc': 'powerpc',
-        'ppc64': 'powerpc64',
-        'ppc64le': 'powerpc64le',
-        'riscv64': 'riscv64gc',
-        's390x': 's390x',
-        'x64': 'x86_64',
-        'x86': 'i686',
-        'x86-64': 'x86_64',
-        'x86_64': 'x86_64'
+        "BePC": "i686",
+        "aarch64": "aarch64",
+        "aarch64eb": "aarch64",
+        "amd64": "x86_64",
+        "arm64": "aarch64",
+        "i386": "i686",
+        "i486": "i686",
+        "i686": "i686",
+        "i686-AT386": "i686",
+        "i786": "i686",
+        "loongarch64": "loongarch64",
+        "m68k": "m68k",
+        "csky": "csky",
+        "powerpc": "powerpc",
+        "powerpc64": "powerpc64",
+        "powerpc64le": "powerpc64le",
+        "ppc": "powerpc",
+        "ppc64": "powerpc64",
+        "ppc64le": "powerpc64le",
+        "riscv64": "riscv64gc",
+        "s390x": "s390x",
+        "x64": "x86_64",
+        "x86": "i686",
+        "x86-64": "x86_64",
+        "x86_64": "x86_64",
     }
 
     # Consider the direct transformation first and then the special cases
     if cputype in cputype_mapper:
         cputype = cputype_mapper[cputype]
-    elif cputype in {'xscale', 'arm'}:
-        cputype = 'arm'
-        if kernel == 'linux-android':
-            kernel = 'linux-androideabi'
-        elif kernel == 'unknown-freebsd':
+    elif cputype in {"xscale", "arm"}:
+        cputype = "arm"
+        if kernel == "linux-android":
+            kernel = "linux-androideabi"
+        elif kernel == "unknown-freebsd":
             cputype = processor
-            kernel = 'unknown-freebsd'
-    elif cputype == 'armv6l':
-        cputype = 'arm'
-        if kernel == 'linux-android':
-            kernel = 'linux-androideabi'
+            kernel = "unknown-freebsd"
+    elif cputype == "armv6l":
+        cputype = "arm"
+        if kernel == "linux-android":
+            kernel = "linux-androideabi"
         else:
-            kernel += 'eabihf'
-    elif cputype in {'armv7l', 'armv8l'}:
-        cputype = 'armv7'
-        if kernel == 'linux-android':
-            kernel = 'linux-androideabi'
+            kernel += "eabihf"
+    elif cputype in {"armv7l", "armv8l"}:
+        cputype = "armv7"
+        if kernel == "linux-android":
+            kernel = "linux-androideabi"
         else:
-            kernel += 'eabihf'
-    elif cputype == 'mips':
-        if sys.byteorder == 'big':
-            cputype = 'mips'
-        elif sys.byteorder == 'little':
-            cputype = 'mipsel'
+            kernel += "eabihf"
+    elif cputype == "mips":
+        if sys.byteorder == "big":
+            cputype = "mips"
+        elif sys.byteorder == "little":
+            cputype = "mipsel"
         else:
             raise ValueError("unknown byteorder: {}".format(sys.byteorder))
-    elif cputype == 'mips64':
-        if sys.byteorder == 'big':
-            cputype = 'mips64'
-        elif sys.byteorder == 'little':
-            cputype = 'mips64el'
+    elif cputype == "mips64":
+        if sys.byteorder == "big":
+            cputype = "mips64"
+        elif sys.byteorder == "little":
+            cputype = "mips64el"
         else:
-            raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
+            raise ValueError("unknown byteorder: {}".format(sys.byteorder))
         # only the n64 ABI is supported, indicate it
-        kernel += 'abi64'
-    elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
+        kernel += "abi64"
+    elif cputype == "sparc" or cputype == "sparcv9" or cputype == "sparc64":
         pass
     else:
         err = "unknown cpu type: {}".format(cputype)
@@ -422,8 +460,8 @@ def default_build_triple(verbose):
 
 @contextlib.contextmanager
 def output(filepath):
-    tmp = filepath + '.tmp'
-    with open(tmp, 'w') as f:
+    tmp = filepath + ".tmp"
+    with open(tmp, "w") as f:
         yield f
     try:
         if os.path.exists(filepath):
@@ -467,6 +505,7 @@ class DownloadInfo:
         self.pattern = pattern
         self.verbose = verbose
 
+
 def download_component(download_info):
     if not os.path.exists(download_info.tarball_path):
         get(
@@ -477,6 +516,7 @@ def download_component(download_info):
             verbose=download_info.verbose,
         )
 
+
 def unpack_component(download_info):
     unpack(
         download_info.tarball_path,
@@ -486,26 +526,30 @@ def unpack_component(download_info):
         verbose=download_info.verbose,
     )
 
+
 class FakeArgs:
     """Used for unit tests to avoid updating all call sites"""
+
     def __init__(self):
-        self.build = ''
-        self.build_dir = ''
+        self.build = ""
+        self.build_dir = ""
         self.clean = False
         self.verbose = False
         self.json_output = False
-        self.color = 'auto'
-        self.warnings = 'default'
+        self.color = "auto"
+        self.warnings = "default"
+
 
 class RustBuild(object):
     """Provide all the methods required to build Rust"""
+
     def __init__(self, config_toml="", args=None):
         if args is None:
             args = FakeArgs()
         self.git_version = None
         self.nix_deps_dir = None
         self._should_fix_bins_and_dylibs = None
-        self.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
+        self.rust_root = os.path.abspath(os.path.join(__file__, "../../.."))
 
         self.config_toml = config_toml
 
@@ -515,26 +559,28 @@ class RustBuild(object):
         self.color = args.color
         self.warnings = args.warnings
 
-        config_verbose_count = self.get_toml('verbose', 'build')
+        config_verbose_count = self.get_toml("verbose", "build")
         if config_verbose_count is not None:
             self.verbose = max(self.verbose, int(config_verbose_count))
 
-        self.use_vendored_sources = self.get_toml('vendor', 'build') == 'true'
-        self.use_locked_deps = self.get_toml('locked-deps', 'build') == 'true'
+        self.use_vendored_sources = self.get_toml("vendor", "build") == "true"
+        self.use_locked_deps = self.get_toml("locked-deps", "build") == "true"
 
-        build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build'
+        build_dir = args.build_dir or self.get_toml("build-dir", "build") or "build"
         self.build_dir = os.path.abspath(build_dir)
 
-        self.stage0_data = parse_stage0_file(os.path.join(self.rust_root, "src", "stage0"))
+        self.stage0_data = parse_stage0_file(
+            os.path.join(self.rust_root, "src", "stage0")
+        )
         self.stage0_compiler = Stage0Toolchain(
-            self.stage0_data["compiler_date"],
-            self.stage0_data["compiler_version"]
+            self.stage0_data["compiler_date"], self.stage0_data["compiler_version"]
+        )
+        self.download_url = (
+            os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"]
         )
-        self.download_url = os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"]
 
         self.build = args.build or self.build_triple()
 
-
     def download_toolchain(self):
         """Fetch the build system for Rust, written in Rust
 
@@ -550,58 +596,73 @@ class RustBuild(object):
 
         key = self.stage0_compiler.date
         is_outdated = self.program_out_of_date(self.rustc_stamp(), key)
-        need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \
-            or is_outdated)
-        need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \
-            or is_outdated)
+        need_rustc = self.rustc().startswith(bin_root) and (
+            not os.path.exists(self.rustc()) or is_outdated
+        )
+        need_cargo = self.cargo().startswith(bin_root) and (
+            not os.path.exists(self.cargo()) or is_outdated
+        )
 
         if need_rustc or need_cargo:
             if os.path.exists(bin_root):
                 # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's
                 # running. Kill it.
                 if platform_is_win32():
-                    print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain")
-                    regex =  '{}\\\\(host|{})\\\\stage0\\\\libexec'.format(
-                        os.path.basename(self.build_dir),
-                        self.build
+                    print(
+                        "Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain"
+                    )
+                    regex = "{}\\\\(host|{})\\\\stage0\\\\libexec".format(
+                        os.path.basename(self.build_dir), self.build
                     )
                     script = (
                         # NOTE: can't use `taskkill` or `Get-Process -Name` because they error if
                         # the server isn't running.
-                        'Get-Process | ' +
-                        'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' +
-                        'Where-Object {{$_.Path -match "{}"}} |'.format(regex) +
-                        'Stop-Process'
+                        "Get-Process | "
+                        + 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |'
+                        + 'Where-Object {{$_.Path -match "{}"}} |'.format(regex)
+                        + "Stop-Process"
                     )
                     run_powershell([script])
                 shutil.rmtree(bin_root)
 
-            cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or
-                os.path.join(self.build_dir, "cache"))
+            cache_dst = self.get_toml("bootstrap-cache-path", "build") or os.path.join(
+                self.build_dir, "cache"
+            )
 
             rustc_cache = os.path.join(cache_dst, key)
             if not os.path.exists(rustc_cache):
                 os.makedirs(rustc_cache)
 
-            tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
+            tarball_suffix = ".tar.gz" if lzma is None else ".tar.xz"
 
-            toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix)
+            toolchain_suffix = "{}-{}{}".format(
+                rustc_channel, self.build, tarball_suffix
+            )
 
             tarballs_to_download = []
 
             if need_rustc:
                 tarballs_to_download.append(
-                    ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build))
+                    (
+                        "rust-std-{}".format(toolchain_suffix),
+                        "rust-std-{}".format(self.build),
+                    )
+                )
+                tarballs_to_download.append(
+                    ("rustc-{}".format(toolchain_suffix), "rustc")
                 )
-                tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc"))
 
             if need_cargo:
-                tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo"))
+                tarballs_to_download.append(
+                    ("cargo-{}".format(toolchain_suffix), "cargo")
+                )
 
             tarballs_download_info = [
                 DownloadInfo(
                     base_download_url=self.download_url,
-                    download_path="dist/{}/{}".format(self.stage0_compiler.date, filename),
+                    download_path="dist/{}/{}".format(
+                        self.stage0_compiler.date, filename
+                    ),
                     bin_root=self.bin_root(),
                     tarball_path=os.path.join(rustc_cache, filename),
                     tarball_suffix=tarball_suffix,
@@ -620,7 +681,11 @@ class RustBuild(object):
             # In Python 2.7, Pool cannot be used as a context manager.
             pool_size = min(len(tarballs_download_info), get_cpus())
             if self.verbose:
-                print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs')
+                print(
+                    "Choosing a pool size of",
+                    pool_size,
+                    "for the unpacking of the tarballs",
+                )
             p = Pool(pool_size)
             try:
                 # FIXME: A cheap workaround for https://github.com/rust-lang/rust/issues/125578,
@@ -639,7 +704,9 @@ class RustBuild(object):
 
                 self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
                 self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
-                self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
+                self.fix_bin_or_dylib(
+                    "{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root)
+                )
                 lib_dir = "{}/lib".format(bin_root)
                 rustlib_bin_dir = "{}/rustlib/{}/bin".format(lib_dir, self.build)
                 self.fix_bin_or_dylib("{}/rust-lld".format(rustlib_bin_dir))
@@ -667,12 +734,15 @@ class RustBuild(object):
         def get_answer():
             default_encoding = sys.getdefaultencoding()
             try:
-                ostype = subprocess.check_output(
-                    ['uname', '-s']).strip().decode(default_encoding)
+                ostype = (
+                    subprocess.check_output(["uname", "-s"])
+                    .strip()
+                    .decode(default_encoding)
+                )
             except subprocess.CalledProcessError:
                 return False
             except OSError as reason:
-                if getattr(reason, 'winerror', None) is not None:
+                if getattr(reason, "winerror", None) is not None:
                     return False
                 raise reason
 
@@ -690,17 +760,23 @@ class RustBuild(object):
             # The latter one does not exist on NixOS when using tmpfs as root.
             try:
                 with open("/etc/os-release", "r") as f:
-                    is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"')
-                                   for ln in f)
+                    is_nixos = any(
+                        ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"')
+                        for ln in f
+                    )
             except FileNotFoundError:
                 is_nixos = False
 
             # If not on NixOS, then warn if user seems to be atop Nix shell
             if not is_nixos:
-                in_nix_shell = os.getenv('IN_NIX_SHELL')
+                in_nix_shell = os.getenv("IN_NIX_SHELL")
                 if in_nix_shell:
-                    eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell),
-                          "you may need to set `patch-binaries-for-nix=true` in config.toml")
+                    eprint(
+                        "The IN_NIX_SHELL environment variable is `{}`;".format(
+                            in_nix_shell
+                        ),
+                        "you may need to set `patch-binaries-for-nix=true` in config.toml",
+                    )
 
             return is_nixos
 
@@ -736,7 +812,7 @@ class RustBuild(object):
             # zlib: Needed as a system dependency of `libLLVM-*.so`.
             # patchelf: Needed for patching ELF binaries (see doc comment above).
             nix_deps_dir = "{}/{}".format(self.build_dir, ".nix-deps")
-            nix_expr = '''
+            nix_expr = """
             with (import <nixpkgs> {});
             symlinkJoin {
               name = "rust-stage0-dependencies";
@@ -746,24 +822,30 @@ class RustBuild(object):
                 stdenv.cc.bintools
               ];
             }
-            '''
+            """
             try:
-                subprocess.check_output([
-                    "nix-build", "-E", nix_expr, "-o", nix_deps_dir,
-                ])
+                subprocess.check_output(
+                    [
+                        "nix-build",
+                        "-E",
+                        nix_expr,
+                        "-o",
+                        nix_deps_dir,
+                    ]
+                )
             except subprocess.CalledProcessError as reason:
                 eprint("WARNING: failed to call nix-build:", reason)
                 return
             self.nix_deps_dir = nix_deps_dir
 
         patchelf = "{}/bin/patchelf".format(nix_deps_dir)
-        rpath_entries = [
-            os.path.join(os.path.realpath(nix_deps_dir), "lib")
-        ]
+        rpath_entries = [os.path.join(os.path.realpath(nix_deps_dir), "lib")]
         patchelf_args = ["--add-rpath", ":".join(rpath_entries)]
         if ".so" not in fname:
             # Finally, set the correct .interp for binaries
-            with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker:
+            with open(
+                "{}/nix-support/dynamic-linker".format(nix_deps_dir)
+            ) as dynamic_linker:
                 patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()]
 
         try:
@@ -781,13 +863,13 @@ class RustBuild(object):
         >>> expected = os.path.join("build", "host", "stage0", ".rustc-stamp")
         >>> assert rb.rustc_stamp() == expected, rb.rustc_stamp()
         """
-        return os.path.join(self.bin_root(), '.rustc-stamp')
+        return os.path.join(self.bin_root(), ".rustc-stamp")
 
     def program_out_of_date(self, stamp_path, key):
         """Check if the given program stamp is out of date"""
         if not os.path.exists(stamp_path) or self.clean:
             return True
-        with open(stamp_path, 'r') as stamp:
+        with open(stamp_path, "r") as stamp:
             return key != stamp.read()
 
     def bin_root(self):
@@ -834,11 +916,11 @@ class RustBuild(object):
     def get_toml_static(config_toml, key, section=None):
         cur_section = None
         for line in config_toml.splitlines():
-            section_match = re.match(r'^\s*\[(.*)\]\s*$', line)
+            section_match = re.match(r"^\s*\[(.*)\]\s*$", line)
             if section_match is not None:
                 cur_section = section_match.group(1)
 
-            match = re.match(r'^{}\s*=(.*)$'.format(key), line)
+            match = re.match(r"^{}\s*=(.*)$".format(key), line)
             if match is not None:
                 value = match.group(1)
                 if section is None or section == cur_section:
@@ -847,11 +929,11 @@ class RustBuild(object):
 
     def cargo(self):
         """Return config path for cargo"""
-        return self.program_config('cargo')
+        return self.program_config("cargo")
 
     def rustc(self):
         """Return config path for rustc"""
-        return self.program_config('rustc')
+        return self.program_config("rustc")
 
     def program_config(self, program):
         """Return config path for the given program at the given stage
@@ -886,12 +968,12 @@ class RustBuild(object):
         """
         start = line.find('"')
         if start != -1:
-            end = start + 1 + line[start + 1:].find('"')
-            return line[start + 1:end]
-        start = line.find('\'')
+            end = start + 1 + line[start + 1 :].find('"')
+            return line[start + 1 : end]
+        start = line.find("'")
         if start != -1:
-            end = start + 1 + line[start + 1:].find('\'')
-            return line[start + 1:end]
+            end = start + 1 + line[start + 1 :].find("'")
+            return line[start + 1 : end]
         return None
 
     def bootstrap_out(self):
@@ -941,24 +1023,37 @@ class RustBuild(object):
             del env["CARGO_BUILD_TARGET"]
         env["CARGO_TARGET_DIR"] = build_dir
         env["RUSTC"] = self.rustc()
-        env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
-            (os.pathsep + env["LD_LIBRARY_PATH"]) \
-            if "LD_LIBRARY_PATH" in env else ""
-        env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
-            (os.pathsep + env["DYLD_LIBRARY_PATH"]) \
-            if "DYLD_LIBRARY_PATH" in env else ""
-        env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
-            (os.pathsep + env["LIBRARY_PATH"]) \
-            if "LIBRARY_PATH" in env else ""
-        env["LIBPATH"] = os.path.join(self.bin_root(), "lib") + \
-            (os.pathsep + env["LIBPATH"]) \
-            if "LIBPATH" in env else ""
+        env["LD_LIBRARY_PATH"] = (
+            os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LD_LIBRARY_PATH"])
+            if "LD_LIBRARY_PATH" in env
+            else ""
+        )
+        env["DYLD_LIBRARY_PATH"] = (
+            os.path.join(self.bin_root(), "lib")
+            + (os.pathsep + env["DYLD_LIBRARY_PATH"])
+            if "DYLD_LIBRARY_PATH" in env
+            else ""
+        )
+        env["LIBRARY_PATH"] = (
+            os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBRARY_PATH"])
+            if "LIBRARY_PATH" in env
+            else ""
+        )
+        env["LIBPATH"] = (
+            os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBPATH"])
+            if "LIBPATH" in env
+            else ""
+        )
 
         # Export Stage0 snapshot compiler related env variables
         build_section = "target.{}".format(self.build)
         host_triple_sanitized = self.build.replace("-", "_")
         var_data = {
-            "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib"
+            "CC": "cc",
+            "CXX": "cxx",
+            "LD": "linker",
+            "AR": "ar",
+            "RANLIB": "ranlib",
         }
         for var_name, toml_key in var_data.items():
             toml_val = self.get_toml(toml_key, build_section)
@@ -1023,13 +1118,16 @@ class RustBuild(object):
         if "RUSTFLAGS_BOOTSTRAP" in env:
             env["RUSTFLAGS"] += " " + env["RUSTFLAGS_BOOTSTRAP"]
 
-        env["PATH"] = os.path.join(self.bin_root(), "bin") + \
-            os.pathsep + env["PATH"]
+        env["PATH"] = os.path.join(self.bin_root(), "bin") + os.pathsep + env["PATH"]
         if not os.path.isfile(self.cargo()):
-            raise Exception("no cargo executable found at `{}`".format(
-                self.cargo()))
-        args = [self.cargo(), "build", "--manifest-path",
-                os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
+            raise Exception("no cargo executable found at `{}`".format(self.cargo()))
+        args = [
+            self.cargo(),
+            "build",
+            "--manifest-path",
+            os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"),
+            "-Zroot-dir=" + self.rust_root,
+        ]
         args.extend("--verbose" for _ in range(self.verbose))
         if self.use_locked_deps:
             args.append("--locked")
@@ -1057,83 +1155,103 @@ class RustBuild(object):
         Note that `default_build_triple` is moderately expensive,
         so use `self.build` where possible.
         """
-        config = self.get_toml('build')
+        config = self.get_toml("build")
         return config or default_build_triple(self.verbose)
 
     def check_vendored_status(self):
         """Check that vendoring is configured properly"""
         # keep this consistent with the equivalent check in bootstrap:
         # https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405
-        if 'SUDO_USER' in os.environ and not self.use_vendored_sources:
+        if "SUDO_USER" in os.environ and not self.use_vendored_sources:
             if os.getuid() == 0:
                 self.use_vendored_sources = True
-                eprint('INFO: looks like you\'re trying to run this command as root')
-                eprint('      and so in order to preserve your $HOME this will now')
-                eprint('      use vendored sources by default.')
+                eprint("INFO: looks like you're trying to run this command as root")
+                eprint("      and so in order to preserve your $HOME this will now")
+                eprint("      use vendored sources by default.")
 
-        cargo_dir = os.path.join(self.rust_root, '.cargo')
+        cargo_dir = os.path.join(self.rust_root, ".cargo")
+        url = "https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz"
         if self.use_vendored_sources:
-            vendor_dir = os.path.join(self.rust_root, 'vendor')
+            vendor_dir = os.path.join(self.rust_root, "vendor")
             if not os.path.exists(vendor_dir):
-                eprint('ERROR: vendoring required, but vendor directory does not exist.')
-                eprint('       Run `x.py vendor` to initialize the vendor directory.')
-                eprint('       Alternatively, use the pre-vendored `rustc-src` dist component.')
-                eprint('       To get a stable/beta/nightly version, download it from: ')
-                eprint('       '
-                'https://forge.rust-lang.org/infra/other-installation-methods.html#source-code')
-                eprint('       To get a specific commit version, download it using the below URL,')
-                eprint('       replacing <commit> with a specific commit checksum: ')
-                eprint('       '
-                'https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz')
-                eprint('       Once you have the source downloaded, place the vendor directory')
-                eprint('       from the archive in the root of the rust project.')
+                eprint(
+                    "ERROR: vendoring required, but vendor directory does not exist."
+                )
+                eprint("       Run `x.py vendor` to initialize the vendor directory.")
+                eprint(
+                    "       Alternatively, use the pre-vendored `rustc-src` dist component."
+                )
+                eprint(
+                    "       To get a stable/beta/nightly version, download it from: "
+                )
+                eprint(
+                    "       "
+                    "https://forge.rust-lang.org/infra/other-installation-methods.html#source-code"
+                )
+                eprint(
+                    "       To get a specific commit version, download it using the below URL,"
+                )
+                eprint("       replacing <commit> with a specific commit checksum: ")
+                eprint("       ", url)
+                eprint(
+                    "       Once you have the source downloaded, place the vendor directory"
+                )
+                eprint("       from the archive in the root of the rust project.")
                 raise Exception("{} not found".format(vendor_dir))
 
             if not os.path.exists(cargo_dir):
-                eprint('ERROR: vendoring required, but .cargo/config does not exist.')
+                eprint("ERROR: vendoring required, but .cargo/config does not exist.")
                 raise Exception("{} not found".format(cargo_dir))
 
+
 def parse_args(args):
     """Parse the command line arguments that the python script needs."""
     parser = argparse.ArgumentParser(add_help=False)
-    parser.add_argument('-h', '--help', action='store_true')
-    parser.add_argument('--config')
-    parser.add_argument('--build-dir')
-    parser.add_argument('--build')
-    parser.add_argument('--color', choices=['always', 'never', 'auto'])
-    parser.add_argument('--clean', action='store_true')
-    parser.add_argument('--json-output', action='store_true')
-    parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default')
-    parser.add_argument('-v', '--verbose', action='count', default=0)
+    parser.add_argument("-h", "--help", action="store_true")
+    parser.add_argument("--config")
+    parser.add_argument("--build-dir")
+    parser.add_argument("--build")
+    parser.add_argument("--color", choices=["always", "never", "auto"])
+    parser.add_argument("--clean", action="store_true")
+    parser.add_argument("--json-output", action="store_true")
+    parser.add_argument(
+        "--warnings", choices=["deny", "warn", "default"], default="default"
+    )
+    parser.add_argument("-v", "--verbose", action="count", default=0)
 
     return parser.parse_known_args(args)[0]
 
+
 def parse_stage0_file(path):
     result = {}
-    with open(path, 'r') as file:
+    with open(path, "r") as file:
         for line in file:
             line = line.strip()
-            if line and not line.startswith('#'):
-                key, value = line.split('=', 1)
+            if line and not line.startswith("#"):
+                key, value = line.split("=", 1)
                 result[key.strip()] = value.strip()
     return result
 
+
 def bootstrap(args):
     """Configure, fetch, build and run the initial bootstrap"""
-    rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
+    rust_root = os.path.abspath(os.path.join(__file__, "../../.."))
 
-    if not os.path.exists(os.path.join(rust_root, '.git')) and \
-            os.path.exists(os.path.join(rust_root, '.github')):
-        eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a "
-               "git clone nor distributed tarball.\nThis build may fail due to missing submodules "
-               "unless you put them in place manually.")
+    if not os.path.exists(os.path.join(rust_root, ".git")) and os.path.exists(
+        os.path.join(rust_root, ".github")
+    ):
+        eprint(
+            "warn: Looks like you are trying to bootstrap Rust from a source that is neither a "
+            "git clone nor distributed tarball.\nThis build may fail due to missing submodules "
+            "unless you put them in place manually."
+        )
 
     # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
     # then `config.toml` in the root directory.
-    toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG')
+    toml_path = args.config or os.getenv("RUST_BOOTSTRAP_CONFIG")
     using_default_path = toml_path is None
     if using_default_path:
-        toml_path = 'config.toml'
+        toml_path = "config.toml"
         if not os.path.exists(toml_path):
             toml_path = os.path.join(rust_root, toml_path)
 
@@ -1143,23 +1261,23 @@ def bootstrap(args):
         with open(toml_path) as config:
             config_toml = config.read()
     else:
-        config_toml = ''
+        config_toml = ""
 
-    profile = RustBuild.get_toml_static(config_toml, 'profile')
+    profile = RustBuild.get_toml_static(config_toml, "profile")
     if profile is not None:
         # Allows creating alias for profile names, allowing
         # profiles to be renamed while maintaining back compatibility
         # Keep in sync with `profile_aliases` in config.rs
-        profile_aliases = {
-            "user": "dist"
-        }
-        include_file = 'config.{}.toml'.format(profile_aliases.get(profile) or profile)
-        include_dir = os.path.join(rust_root, 'src', 'bootstrap', 'defaults')
+        profile_aliases = {"user": "dist"}
+        include_file = "config.{}.toml".format(profile_aliases.get(profile) or profile)
+        include_dir = os.path.join(rust_root, "src", "bootstrap", "defaults")
         include_path = os.path.join(include_dir, include_file)
 
         if not os.path.exists(include_path):
-            raise Exception("Unrecognized config profile '{}'. Check src/bootstrap/defaults"
-            " for available options.".format(profile))
+            raise Exception(
+                "Unrecognized config profile '{}'. Check src/bootstrap/defaults"
+                " for available options.".format(profile)
+            )
 
         # HACK: This works because `self.get_toml()` returns the first match it finds for a
         # specific key, so appending our defaults at the end allows the user to override them
@@ -1183,6 +1301,8 @@ def bootstrap(args):
     args = [build.bootstrap_binary()]
     args.extend(sys.argv[1:])
     env = os.environ.copy()
+    # The Python process ID is used when creating a Windows job object
+    # (see src\bootstrap\src\utils\job.rs)
     env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
     env["BOOTSTRAP_PYTHON"] = sys.executable
     run(args, env=env, verbose=build.verbose, is_bootstrap=True)
@@ -1193,8 +1313,8 @@ def main():
     start_time = time()
 
     # x.py help <cmd> ...
-    if len(sys.argv) > 1 and sys.argv[1] == 'help':
-        sys.argv[1] = '-h'
+    if len(sys.argv) > 1 and sys.argv[1] == "help":
+        sys.argv[1] = "-h"
 
     args = parse_args(sys.argv)
     help_triggered = args.help or len(sys.argv) == 1
@@ -1204,14 +1324,15 @@ def main():
     if help_triggered:
         eprint(
             "INFO: Downloading and building bootstrap before processing --help command.\n"
-            "      See src/bootstrap/README.md for help with common commands.")
+            "      See src/bootstrap/README.md for help with common commands."
+        )
 
     exit_code = 0
     success_word = "successfully"
     try:
         bootstrap(args)
     except (SystemExit, KeyboardInterrupt) as error:
-        if hasattr(error, 'code') and isinstance(error.code, int):
+        if hasattr(error, "code") and isinstance(error.code, int):
             exit_code = error.code
         else:
             exit_code = 1
@@ -1219,9 +1340,14 @@ def main():
         success_word = "unsuccessfully"
 
     if not help_triggered:
-        eprint("Build completed", success_word, "in", format_build_time(time() - start_time))
+        eprint(
+            "Build completed",
+            success_word,
+            "in",
+            format_build_time(time() - start_time),
+        )
     sys.exit(exit_code)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 70ed12b96e8..7494536539d 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -16,8 +16,9 @@ from shutil import rmtree
 bootstrap_dir = os.path.dirname(os.path.abspath(__file__))
 # For the import below, have Python search in src/bootstrap first.
 sys.path.insert(0, bootstrap_dir)
-import bootstrap # noqa: E402
-import configure # noqa: E402
+import bootstrap  # noqa: E402
+import configure  # noqa: E402
+
 
 def serialize_and_parse(configure_args, bootstrap_args=None):
     from io import StringIO
@@ -32,15 +33,20 @@ def serialize_and_parse(configure_args, bootstrap_args=None):
 
     try:
         import tomllib
+
         # Verify this is actually valid TOML.
         tomllib.loads(build.config_toml)
     except ImportError:
-        print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr)
+        print(
+            "WARNING: skipping TOML validation, need at least python 3.11",
+            file=sys.stderr,
+        )
     return build
 
 
 class VerifyTestCase(unittest.TestCase):
     """Test Case for verify"""
+
     def setUp(self):
         self.container = tempfile.mkdtemp()
         self.src = os.path.join(self.container, "src.txt")
@@ -68,14 +74,14 @@ class VerifyTestCase(unittest.TestCase):
 
 class ProgramOutOfDate(unittest.TestCase):
     """Test if a program is out of date"""
+
     def setUp(self):
         self.container = tempfile.mkdtemp()
         os.mkdir(os.path.join(self.container, "stage0"))
         self.build = bootstrap.RustBuild()
         self.build.date = "2017-06-15"
         self.build.build_dir = self.container
-        self.rustc_stamp_path = os.path.join(self.container, "stage0",
-                                             ".rustc-stamp")
+        self.rustc_stamp_path = os.path.join(self.container, "stage0", ".rustc-stamp")
         self.key = self.build.date + str(None)
 
     def tearDown(self):
@@ -97,11 +103,14 @@ class ProgramOutOfDate(unittest.TestCase):
         """Return False both dates match"""
         with open(self.rustc_stamp_path, "w") as rustc_stamp:
             rustc_stamp.write("2017-06-15None")
-        self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
+        self.assertFalse(
+            self.build.program_out_of_date(self.rustc_stamp_path, self.key)
+        )
 
 
 class ParseArgsInConfigure(unittest.TestCase):
     """Test if `parse_args` function in `configure.py` works properly"""
+
     @patch("configure.err")
     def test_unknown_args(self, err):
         # It should be print an error message if the argument doesn't start with '--'
@@ -148,28 +157,35 @@ class ParseArgsInConfigure(unittest.TestCase):
 
 class GenerateAndParseConfig(unittest.TestCase):
     """Test that we can serialize and deserialize a config.toml file"""
+
     def test_no_args(self):
         build = serialize_and_parse([])
-        self.assertEqual(build.get_toml("profile"), 'dist')
+        self.assertEqual(build.get_toml("profile"), "dist")
         self.assertIsNone(build.get_toml("llvm.download-ci-llvm"))
 
     def test_set_section(self):
         build = serialize_and_parse(["--set", "llvm.download-ci-llvm"])
-        self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true')
+        self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), "true")
 
     def test_set_target(self):
         build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"])
-        self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc')
+        self.assertEqual(
+            build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), "gcc"
+        )
 
     def test_set_top_level(self):
         build = serialize_and_parse(["--set", "profile=compiler"])
-        self.assertEqual(build.get_toml("profile"), 'compiler')
+        self.assertEqual(build.get_toml("profile"), "compiler")
 
     def test_set_codegen_backends(self):
         build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"])
-        self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1)
+        self.assertNotEqual(
+            build.config_toml.find("codegen-backends = ['cranelift']"), -1
+        )
         build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"])
-        self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1)
+        self.assertNotEqual(
+            build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1
+        )
         build = serialize_and_parse(["--enable-full-tools"])
         self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1)
 
@@ -223,7 +239,7 @@ class BuildBootstrap(unittest.TestCase):
         self.assertTrue("--timings" in args)
 
     def test_warnings(self):
-        for toml_warnings in ['false', 'true', None]:
+        for toml_warnings in ["false", "true", None]:
             configure_args = []
             if toml_warnings is not None:
                 configure_args = ["--set", "rust.deny-warnings=" + toml_warnings]
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 70f4e70962a..71750022145 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -6,11 +6,12 @@ from __future__ import absolute_import, division, print_function
 import shlex
 import sys
 import os
+
 rust_dir = os.path.dirname(os.path.abspath(__file__))
 rust_dir = os.path.dirname(rust_dir)
 rust_dir = os.path.dirname(rust_dir)
 sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
-import bootstrap # noqa: E402
+import bootstrap  # noqa: E402
 
 
 class Option(object):
@@ -32,26 +33,62 @@ def v(*args):
     options.append(Option(*args, value=True))
 
 
-o("debug", "rust.debug", "enables debugging environment; does not affect optimization of bootstrapped code")
+o(
+    "debug",
+    "rust.debug",
+    "enables debugging environment; does not affect optimization of bootstrapped code",
+)
 o("docs", "build.docs", "build standard library documentation")
 o("compiler-docs", "build.compiler-docs", "build compiler documentation")
 o("optimize-tests", "rust.optimize-tests", "build tests with optimizations")
 o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests")
-o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")
+o(
+    "ccache",
+    "llvm.ccache",
+    "invoke gcc/clang via ccache to reuse object files between builds",
+)
 o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds")
 o("local-rust", None, "use an installed rustc rather than downloading a snapshot")
 v("local-rust-root", None, "set prefix for local rust binary")
-o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version")
-o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM")
-o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)")
+o(
+    "local-rebuild",
+    "build.local-rebuild",
+    "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version",
+)
+o(
+    "llvm-static-stdcpp",
+    "llvm.static-libstdcpp",
+    "statically link to libstdc++ for LLVM",
+)
+o(
+    "llvm-link-shared",
+    "llvm.link-shared",
+    "prefer shared linking to LLVM (llvm-config --link-shared)",
+)
 o("rpath", "rust.rpath", "build rpaths into rustc itself")
 o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests")
-o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)")
+o(
+    "ninja",
+    "llvm.ninja",
+    "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)",
+)
 o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date")
 o("vendor", "build.vendor", "enable usage of vendored Rust crates")
-o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)")
-o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
-o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo")
+o(
+    "sanitizers",
+    "build.sanitizers",
+    "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)",
+)
+o(
+    "dist-src",
+    "rust.dist-src",
+    "when building tarballs enables building a source tarball",
+)
+o(
+    "cargo-native-static",
+    "build.cargo-native-static",
+    "static native libraries in cargo",
+)
 o("profiler", "build.profiler", "build the profiler runtime")
 o("full-tools", None, "enable all tools")
 o("lld", "rust.lld", "build lld")
@@ -59,7 +96,11 @@ o("llvm-bitcode-linker", "rust.llvm-bitcode-linker", "build llvm bitcode linker"
 o("clang", "llvm.clang", "build clang")
 o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
 o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
-o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains")
+o(
+    "patch-binaries-for-nix",
+    "build.patch-binaries-for-nix",
+    "whether patch binaries for usage with Nix toolchains",
+)
 o("new-symbol-mangling", "rust.new-symbol-mangling", "use symbol-mangling-version v0")
 
 v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
@@ -76,16 +117,48 @@ o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
 o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support")
 o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
 o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
-o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions")
+o(
+    "debug-assertions-std",
+    "rust.debug-assertions-std",
+    "build the standard library with debugging assertions",
+)
 o("overflow-checks", "rust.overflow-checks", "build with overflow checks")
-o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks")
-o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata")
+o(
+    "overflow-checks-std",
+    "rust.overflow-checks-std",
+    "build the standard library with overflow checks",
+)
+o(
+    "llvm-release-debuginfo",
+    "llvm.release-debuginfo",
+    "build LLVM with debugger metadata",
+)
 v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code")
-v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler")
-v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library")
-v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools")
-v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest")
-v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
+v(
+    "debuginfo-level-rustc",
+    "rust.debuginfo-level-rustc",
+    "debuginfo level for the compiler",
+)
+v(
+    "debuginfo-level-std",
+    "rust.debuginfo-level-std",
+    "debuginfo level for the standard library",
+)
+v(
+    "debuginfo-level-tools",
+    "rust.debuginfo-level-tools",
+    "debuginfo level for the tools",
+)
+v(
+    "debuginfo-level-tests",
+    "rust.debuginfo-level-tests",
+    "debuginfo level for the test suites run with compiletest",
+)
+v(
+    "save-toolstates",
+    "rust.save-toolstates",
+    "save build and test status of external tools into this file",
+)
 
 v("prefix", "install.prefix", "set installation prefix")
 v("localstatedir", "install.localstatedir", "local state directory")
@@ -102,50 +175,117 @@ v("llvm-config", None, "set path to llvm-config")
 v("llvm-filecheck", None, "set path to LLVM's FileCheck utility")
 v("python", "build.python", "set path to python")
 v("android-ndk", "build.android-ndk", "set path to Android NDK")
-v("musl-root", "target.x86_64-unknown-linux-musl.musl-root",
-  "MUSL root installation directory (deprecated)")
-v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
-  "x86_64-unknown-linux-musl install directory")
-v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
-  "i586-unknown-linux-musl install directory")
-v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
-  "i686-unknown-linux-musl install directory")
-v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
-  "arm-unknown-linux-musleabi install directory")
-v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root",
-  "arm-unknown-linux-musleabihf install directory")
-v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root",
-  "armv5te-unknown-linux-musleabi install directory")
-v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root",
-  "armv7-unknown-linux-musleabi install directory")
-v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root",
-  "armv7-unknown-linux-musleabihf install directory")
-v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root",
-  "aarch64-unknown-linux-musl install directory")
-v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root",
-  "mips-unknown-linux-musl install directory")
-v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root",
-  "mipsel-unknown-linux-musl install directory")
-v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root",
-  "mips64-unknown-linux-muslabi64 install directory")
-v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root",
-  "mips64el-unknown-linux-muslabi64 install directory")
-v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root",
-  "riscv32gc-unknown-linux-musl install directory")
-v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root",
-  "riscv64gc-unknown-linux-musl install directory")
-v("musl-root-loongarch64", "target.loongarch64-unknown-linux-musl.musl-root",
-  "loongarch64-unknown-linux-musl install directory")
-v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
-  "rootfs in qemu testing, you probably don't want to use this")
-v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
-  "rootfs in qemu testing, you probably don't want to use this")
-v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
-  "rootfs in qemu testing, you probably don't want to use this")
-v("experimental-targets", "llvm.experimental-targets",
-  "experimental LLVM targets to build")
+v(
+    "musl-root",
+    "target.x86_64-unknown-linux-musl.musl-root",
+    "MUSL root installation directory (deprecated)",
+)
+v(
+    "musl-root-x86_64",
+    "target.x86_64-unknown-linux-musl.musl-root",
+    "x86_64-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-i586",
+    "target.i586-unknown-linux-musl.musl-root",
+    "i586-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-i686",
+    "target.i686-unknown-linux-musl.musl-root",
+    "i686-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-arm",
+    "target.arm-unknown-linux-musleabi.musl-root",
+    "arm-unknown-linux-musleabi install directory",
+)
+v(
+    "musl-root-armhf",
+    "target.arm-unknown-linux-musleabihf.musl-root",
+    "arm-unknown-linux-musleabihf install directory",
+)
+v(
+    "musl-root-armv5te",
+    "target.armv5te-unknown-linux-musleabi.musl-root",
+    "armv5te-unknown-linux-musleabi install directory",
+)
+v(
+    "musl-root-armv7",
+    "target.armv7-unknown-linux-musleabi.musl-root",
+    "armv7-unknown-linux-musleabi install directory",
+)
+v(
+    "musl-root-armv7hf",
+    "target.armv7-unknown-linux-musleabihf.musl-root",
+    "armv7-unknown-linux-musleabihf install directory",
+)
+v(
+    "musl-root-aarch64",
+    "target.aarch64-unknown-linux-musl.musl-root",
+    "aarch64-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-mips",
+    "target.mips-unknown-linux-musl.musl-root",
+    "mips-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-mipsel",
+    "target.mipsel-unknown-linux-musl.musl-root",
+    "mipsel-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-mips64",
+    "target.mips64-unknown-linux-muslabi64.musl-root",
+    "mips64-unknown-linux-muslabi64 install directory",
+)
+v(
+    "musl-root-mips64el",
+    "target.mips64el-unknown-linux-muslabi64.musl-root",
+    "mips64el-unknown-linux-muslabi64 install directory",
+)
+v(
+    "musl-root-riscv32gc",
+    "target.riscv32gc-unknown-linux-musl.musl-root",
+    "riscv32gc-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-riscv64gc",
+    "target.riscv64gc-unknown-linux-musl.musl-root",
+    "riscv64gc-unknown-linux-musl install directory",
+)
+v(
+    "musl-root-loongarch64",
+    "target.loongarch64-unknown-linux-musl.musl-root",
+    "loongarch64-unknown-linux-musl install directory",
+)
+v(
+    "qemu-armhf-rootfs",
+    "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
+    "rootfs in qemu testing, you probably don't want to use this",
+)
+v(
+    "qemu-aarch64-rootfs",
+    "target.aarch64-unknown-linux-gnu.qemu-rootfs",
+    "rootfs in qemu testing, you probably don't want to use this",
+)
+v(
+    "qemu-riscv64-rootfs",
+    "target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
+    "rootfs in qemu testing, you probably don't want to use this",
+)
+v(
+    "experimental-targets",
+    "llvm.experimental-targets",
+    "experimental LLVM targets to build",
+)
 v("release-channel", "rust.channel", "the name of the release channel to build")
-v("release-description", "rust.description", "optional descriptive string for version output")
+v(
+    "release-description",
+    "rust.description",
+    "optional descriptive string for version output",
+)
 v("dist-compression-formats", None, "List of compression formats to use")
 
 # Used on systems where "cc" is unavailable
@@ -154,7 +294,11 @@ v("default-linker", "rust.default-linker", "the default linker")
 # Many of these are saved below during the "writing configuration" step
 # (others are conditionally saved).
 o("manage-submodules", "build.submodules", "let the build manage the git submodules")
-o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)")
+o(
+    "full-bootstrap",
+    "build.full-bootstrap",
+    "build three compilers instead of two (not recommended except for testing reproducible builds)",
+)
 o("extended", "build.extended", "build an extended rust tool set")
 
 v("bootstrap-cache-path", None, "use provided path for the bootstrap cache")
@@ -165,8 +309,16 @@ v("host", None, "List of GNUs ./configure syntax LLVM host triples")
 v("target", None, "List of GNUs ./configure syntax LLVM target triples")
 
 # Options specific to this configure script
-o("option-checking", None, "complain about unrecognized options in this configure script")
-o("verbose-configure", None, "don't truncate options when printing them in this configure script")
+o(
+    "option-checking",
+    None,
+    "complain about unrecognized options in this configure script",
+)
+o(
+    "verbose-configure",
+    None,
+    "don't truncate options when printing them in this configure script",
+)
 v("set", None, "set arbitrary key/value pairs in TOML configuration")
 
 
@@ -178,39 +330,42 @@ def err(msg):
     print("\nconfigure: ERROR: " + msg + "\n")
     sys.exit(1)
 
+
 def is_value_list(key):
     for option in options:
-        if option.name == key and option.desc.startswith('List of'):
+        if option.name == key and option.desc.startswith("List of"):
             return True
     return False
 
-if '--help' in sys.argv or '-h' in sys.argv:
-    print('Usage: ./configure [options]')
-    print('')
-    print('Options')
+
+if "--help" in sys.argv or "-h" in sys.argv:
+    print("Usage: ./configure [options]")
+    print("")
+    print("Options")
     for option in options:
-        if 'android' in option.name:
+        if "android" in option.name:
             # no one needs to know about these obscure options
             continue
         if option.value:
-            print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc))
+            print("\t{:30} {}".format("--{}=VAL".format(option.name), option.desc))
         else:
-            print('\t--enable-{:25} OR --disable-{}'.format(option.name, option.name))
-            print('\t\t' + option.desc)
-    print('')
-    print('This configure script is a thin configuration shim over the true')
-    print('configuration system, `config.toml`. You can explore the comments')
-    print('in `config.example.toml` next to this configure script to see')
-    print('more information about what each option is. Additionally you can')
-    print('pass `--set` as an argument to set arbitrary key/value pairs')
-    print('in the TOML configuration if desired')
-    print('')
-    print('Also note that all options which take `--enable` can similarly')
-    print('be passed with `--disable-foo` to forcibly disable the option')
+            print("\t--enable-{:25} OR --disable-{}".format(option.name, option.name))
+            print("\t\t" + option.desc)
+    print("")
+    print("This configure script is a thin configuration shim over the true")
+    print("configuration system, `config.toml`. You can explore the comments")
+    print("in `config.example.toml` next to this configure script to see")
+    print("more information about what each option is. Additionally you can")
+    print("pass `--set` as an argument to set arbitrary key/value pairs")
+    print("in the TOML configuration if desired")
+    print("")
+    print("Also note that all options which take `--enable` can similarly")
+    print("be passed with `--disable-foo` to forcibly disable the option")
     sys.exit(0)
 
 VERBOSE = False
 
+
 # Parse all command line arguments into one of these three lists, handling
 # boolean and value-based options separately
 def parse_args(args):
@@ -222,7 +377,7 @@ def parse_args(args):
     while i < len(args):
         arg = args[i]
         i += 1
-        if not arg.startswith('--'):
+        if not arg.startswith("--"):
             unknown_args.append(arg)
             continue
 
@@ -230,7 +385,7 @@ def parse_args(args):
         for option in options:
             value = None
             if option.value:
-                keyval = arg[2:].split('=', 1)
+                keyval = arg[2:].split("=", 1)
                 key = keyval[0]
                 if option.name != key:
                     continue
@@ -244,9 +399,9 @@ def parse_args(args):
                     need_value_args.append(arg)
                     continue
             else:
-                if arg[2:] == 'enable-' + option.name:
+                if arg[2:] == "enable-" + option.name:
                     value = True
-                elif arg[2:] == 'disable-' + option.name:
+                elif arg[2:] == "disable-" + option.name:
                     value = False
                 else:
                     continue
@@ -263,8 +418,9 @@ def parse_args(args):
     # NOTE: here and a few other places, we use [-1] to apply the *last* value
     # passed.  But if option-checking is enabled, then the known_args loop will
     # also assert that options are only passed once.
-    option_checking = ('option-checking' not in known_args
-                    or known_args['option-checking'][-1][1])
+    option_checking = (
+        "option-checking" not in known_args or known_args["option-checking"][-1][1]
+    )
     if option_checking:
         if len(unknown_args) > 0:
             err("Option '" + unknown_args[0] + "' is not recognized")
@@ -272,18 +428,18 @@ def parse_args(args):
             err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0]))
 
     global VERBOSE
-    VERBOSE = 'verbose-configure' in known_args
+    VERBOSE = "verbose-configure" in known_args
 
     config = {}
 
-    set('build.configure-args', args, config)
+    set("build.configure-args", args, config)
     apply_args(known_args, option_checking, config)
     return parse_example_config(known_args, config)
 
 
 def build(known_args):
-    if 'build' in known_args:
-        return known_args['build'][-1][1]
+    if "build" in known_args:
+        return known_args["build"][-1][1]
     return bootstrap.default_build_triple(verbose=False)
 
 
@@ -291,7 +447,7 @@ def set(key, value, config):
     if isinstance(value, list):
         # Remove empty values, which value.split(',') tends to generate and
         # replace single quotes for double quotes to ensure correct parsing.
-        value = [v.replace('\'', '"') for v in value if v]
+        value = [v.replace("'", '"') for v in value if v]
 
     s = "{:20} := {}".format(key, value)
     if len(s) < 70 or VERBOSE:
@@ -310,7 +466,7 @@ def set(key, value, config):
     for i, part in enumerate(parts):
         if i == len(parts) - 1:
             if is_value_list(part) and isinstance(value, str):
-                value = value.split(',')
+                value = value.split(",")
             arr[part] = value
         else:
             if part not in arr:
@@ -321,9 +477,9 @@ def set(key, value, config):
 def apply_args(known_args, option_checking, config):
     for key in known_args:
         # The `set` option is special and can be passed a bunch of times
-        if key == 'set':
+        if key == "set":
             for _option, value in known_args[key]:
-                keyval = value.split('=', 1)
+                keyval = value.split("=", 1)
                 if len(keyval) == 1 or keyval[1] == "true":
                     value = True
                 elif keyval[1] == "false":
@@ -348,50 +504,55 @@ def apply_args(known_args, option_checking, config):
         # that here.
         build_triple = build(known_args)
 
-        if option.name == 'sccache':
-            set('llvm.ccache', 'sccache', config)
-        elif option.name == 'local-rust':
-            for path in os.environ['PATH'].split(os.pathsep):
-                if os.path.exists(path + '/rustc'):
-                    set('build.rustc', path + '/rustc', config)
+        if option.name == "sccache":
+            set("llvm.ccache", "sccache", config)
+        elif option.name == "local-rust":
+            for path in os.environ["PATH"].split(os.pathsep):
+                if os.path.exists(path + "/rustc"):
+                    set("build.rustc", path + "/rustc", config)
                     break
-            for path in os.environ['PATH'].split(os.pathsep):
-                if os.path.exists(path + '/cargo'):
-                    set('build.cargo', path + '/cargo', config)
+            for path in os.environ["PATH"].split(os.pathsep):
+                if os.path.exists(path + "/cargo"):
+                    set("build.cargo", path + "/cargo", config)
                     break
-        elif option.name == 'local-rust-root':
-            set('build.rustc', value + '/bin/rustc', config)
-            set('build.cargo', value + '/bin/cargo', config)
-        elif option.name == 'llvm-root':
-            set('target.{}.llvm-config'.format(build_triple), value + '/bin/llvm-config', config)
-        elif option.name == 'llvm-config':
-            set('target.{}.llvm-config'.format(build_triple), value, config)
-        elif option.name == 'llvm-filecheck':
-            set('target.{}.llvm-filecheck'.format(build_triple), value, config)
-        elif option.name == 'tools':
-            set('build.tools', value.split(','), config)
-        elif option.name == 'bootstrap-cache-path':
-            set('build.bootstrap-cache-path', value, config)
-        elif option.name == 'codegen-backends':
-            set('rust.codegen-backends', value.split(','), config)
-        elif option.name == 'host':
-            set('build.host', value.split(','), config)
-        elif option.name == 'target':
-            set('build.target', value.split(','), config)
-        elif option.name == 'full-tools':
-            set('rust.codegen-backends', ['llvm'], config)
-            set('rust.lld', True, config)
-            set('rust.llvm-tools', True, config)
-            set('rust.llvm-bitcode-linker', True, config)
-            set('build.extended', True, config)
-        elif option.name in ['option-checking', 'verbose-configure']:
+        elif option.name == "local-rust-root":
+            set("build.rustc", value + "/bin/rustc", config)
+            set("build.cargo", value + "/bin/cargo", config)
+        elif option.name == "llvm-root":
+            set(
+                "target.{}.llvm-config".format(build_triple),
+                value + "/bin/llvm-config",
+                config,
+            )
+        elif option.name == "llvm-config":
+            set("target.{}.llvm-config".format(build_triple), value, config)
+        elif option.name == "llvm-filecheck":
+            set("target.{}.llvm-filecheck".format(build_triple), value, config)
+        elif option.name == "tools":
+            set("build.tools", value.split(","), config)
+        elif option.name == "bootstrap-cache-path":
+            set("build.bootstrap-cache-path", value, config)
+        elif option.name == "codegen-backends":
+            set("rust.codegen-backends", value.split(","), config)
+        elif option.name == "host":
+            set("build.host", value.split(","), config)
+        elif option.name == "target":
+            set("build.target", value.split(","), config)
+        elif option.name == "full-tools":
+            set("rust.codegen-backends", ["llvm"], config)
+            set("rust.lld", True, config)
+            set("rust.llvm-tools", True, config)
+            set("rust.llvm-bitcode-linker", True, config)
+            set("build.extended", True, config)
+        elif option.name in ["option-checking", "verbose-configure"]:
             # this was handled above
             pass
-        elif option.name == 'dist-compression-formats':
-            set('dist.compression-formats', value.split(','), config)
+        elif option.name == "dist-compression-formats":
+            set("dist.compression-formats", value.split(","), config)
         else:
             raise RuntimeError("unhandled option {}".format(option.name))
 
+
 # "Parse" the `config.example.toml` file into the various sections, and we'll
 # use this as a template of a `config.toml` to write out which preserves
 # all the various comments and whatnot.
@@ -406,20 +567,22 @@ def parse_example_config(known_args, config):
     targets = {}
     top_level_keys = []
 
-    with open(rust_dir + '/config.example.toml') as example_config:
+    with open(rust_dir + "/config.example.toml") as example_config:
         example_lines = example_config.read().split("\n")
     for line in example_lines:
         if cur_section is None:
-            if line.count('=') == 1:
-                top_level_key = line.split('=')[0]
-                top_level_key = top_level_key.strip(' #')
+            if line.count("=") == 1:
+                top_level_key = line.split("=")[0]
+                top_level_key = top_level_key.strip(" #")
                 top_level_keys.append(top_level_key)
-        if line.startswith('['):
+        if line.startswith("["):
             cur_section = line[1:-1]
-            if cur_section.startswith('target'):
-                cur_section = 'target'
-            elif '.' in cur_section:
-                raise RuntimeError("don't know how to deal with section: {}".format(cur_section))
+            if cur_section.startswith("target"):
+                cur_section = "target"
+            elif "." in cur_section:
+                raise RuntimeError(
+                    "don't know how to deal with section: {}".format(cur_section)
+                )
             sections[cur_section] = [line]
             section_order.append(cur_section)
         else:
@@ -428,22 +591,25 @@ def parse_example_config(known_args, config):
     # Fill out the `targets` array by giving all configured targets a copy of the
     # `target` section we just loaded from the example config
     configured_targets = [build(known_args)]
-    if 'build' in config:
-        if 'host' in config['build']:
-            configured_targets += config['build']['host']
-        if 'target' in config['build']:
-            configured_targets += config['build']['target']
-    if 'target' in config:
-        for target in config['target']:
+    if "build" in config:
+        if "host" in config["build"]:
+            configured_targets += config["build"]["host"]
+        if "target" in config["build"]:
+            configured_targets += config["build"]["target"]
+    if "target" in config:
+        for target in config["target"]:
             configured_targets.append(target)
     for target in configured_targets:
-        targets[target] = sections['target'][:]
+        targets[target] = sections["target"][:]
         # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target.
         # Avoid using quotes unless it's necessary.
-        targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target)
+        targets[target][0] = targets[target][0].replace(
+            "x86_64-unknown-linux-gnu",
+            "'{}'".format(target) if "." in target else target,
+        )
 
-    if 'profile' not in config:
-        set('profile', 'dist', config)
+    if "profile" not in config:
+        set("profile", "dist", config)
     configure_file(sections, top_level_keys, targets, config)
     return section_order, sections, targets
 
@@ -467,7 +633,7 @@ def to_toml(value):
         else:
             return "false"
     elif isinstance(value, list):
-        return '[' + ', '.join(map(to_toml, value)) + ']'
+        return "[" + ", ".join(map(to_toml, value)) + "]"
     elif isinstance(value, str):
         # Don't put quotes around numeric values
         if is_number(value):
@@ -475,9 +641,18 @@ def to_toml(value):
         else:
             return "'" + value + "'"
     elif isinstance(value, dict):
-        return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}"
+        return (
+            "{"
+            + ", ".join(
+                map(
+                    lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])),
+                    value.items(),
+                )
+            )
+            + "}"
+        )
     else:
-        raise RuntimeError('no toml')
+        raise RuntimeError("no toml")
 
 
 def configure_section(lines, config):
@@ -485,7 +660,7 @@ def configure_section(lines, config):
         value = config[key]
         found = False
         for i, line in enumerate(lines):
-            if not line.startswith('#' + key + ' = '):
+            if not line.startswith("#" + key + " = "):
                 continue
             found = True
             lines[i] = "{} = {}".format(key, to_toml(value))
@@ -501,7 +676,9 @@ def configure_section(lines, config):
 
 def configure_top_level_key(lines, top_level_key, value):
     for i, line in enumerate(lines):
-        if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '):
+        if line.startswith("#" + top_level_key + " = ") or line.startswith(
+            top_level_key + " = "
+        ):
             lines[i] = "{} = {}".format(top_level_key, to_toml(value))
             return
 
@@ -512,11 +689,13 @@ def configure_top_level_key(lines, top_level_key, value):
 def configure_file(sections, top_level_keys, targets, config):
     for section_key, section_config in config.items():
         if section_key not in sections and section_key not in top_level_keys:
-            raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key))
+            raise RuntimeError(
+                "config key {} not in sections or top_level_keys".format(section_key)
+            )
         if section_key in top_level_keys:
             configure_top_level_key(sections[None], section_key, section_config)
 
-        elif  section_key == 'target':
+        elif section_key == "target":
             for target in section_config:
                 configure_section(targets[target], section_config[target])
         else:
@@ -536,18 +715,19 @@ def write_uncommented(target, f):
             block = []
             is_comment = True
             continue
-        is_comment = is_comment and line.startswith('#')
+        is_comment = is_comment and line.startswith("#")
     return f
 
 
 def write_config_toml(writer, section_order, targets, sections):
     for section in section_order:
-        if section == 'target':
+        if section == "target":
             for target in targets:
                 writer = write_uncommented(targets[target], writer)
         else:
             writer = write_uncommented(sections[section], writer)
 
+
 def quit_if_file_exists(file):
     if os.path.isfile(file):
         msg = "Existing '{}' detected. Exiting".format(file)
@@ -559,9 +739,10 @@ def quit_if_file_exists(file):
 
         err(msg)
 
+
 if __name__ == "__main__":
     # If 'config.toml' already exists, exit the script at this point
-    quit_if_file_exists('config.toml')
+    quit_if_file_exists("config.toml")
 
     if "GITHUB_ACTIONS" in os.environ:
         print("::group::Configure the build")
@@ -575,13 +756,13 @@ if __name__ == "__main__":
     # order that we read it in.
     p("")
     p("writing `config.toml` in current directory")
-    with bootstrap.output('config.toml') as f:
+    with bootstrap.output("config.toml") as f:
         write_config_toml(f, section_order, targets, sections)
 
-    with bootstrap.output('Makefile') as f:
-        contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in')
+    with bootstrap.output("Makefile") as f:
+        contents = os.path.join(rust_dir, "src", "bootstrap", "mk", "Makefile.in")
         contents = open(contents).read()
-        contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/')
+        contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + "/")
         contents = contents.replace("$(CFG_PYTHON)", sys.executable)
         f.write(contents)
 
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 92c8f5dc452..a1f38b9ac14 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -108,11 +108,13 @@ ci-msvc: ci-msvc-py ci-msvc-ps1
 
 ## MingW native builders
 
-# test both x and bootstrap entrypoints
+# Set of tests that should represent half of the time of the test suite.
+# Used to split tests across multiple CI runners.
+# Test both x and bootstrap entrypoints.
 ci-mingw-x:
-	$(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy
+	$(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src
 ci-mingw-bootstrap:
-	$(Q)$(BOOTSTRAP) test --stage 2 --skip tidy
+	$(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest
 ci-mingw: ci-mingw-x ci-mingw-bootstrap
 
 .PHONY: dist
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 409a644b9be..74dfe2e7ec8 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -48,9 +48,9 @@ fn main() {
             err => {
                 drop(err);
                 if let Ok(pid) = pid {
-                    println!("WARNING: build directory locked by process {pid}, waiting for lock");
+                    eprintln!("WARNING: build directory locked by process {pid}, waiting for lock");
                 } else {
-                    println!("WARNING: build directory locked, waiting for lock");
+                    eprintln!("WARNING: build directory locked, waiting for lock");
                 }
                 let mut lock = t!(build_lock.write());
                 t!(lock.write(process::id().to_string().as_ref()));
@@ -70,13 +70,13 @@ fn main() {
     // changelog warning, not the `x.py setup` message.
     let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
     if suggest_setup {
-        println!("WARNING: you have not made a `config.toml`");
-        println!(
+        eprintln!("WARNING: you have not made a `config.toml`");
+        eprintln!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        println!("{suggestion}");
+        eprintln!("{suggestion}");
     }
 
     let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
@@ -86,30 +86,30 @@ fn main() {
     Build::new(config).build();
 
     if suggest_setup {
-        println!("WARNING: you have not made a `config.toml`");
-        println!(
+        eprintln!("WARNING: you have not made a `config.toml`");
+        eprintln!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        println!("{suggestion}");
+        eprintln!("{suggestion}");
     }
 
     // Give a warning if the pre-commit script is in pre-commit and not pre-push.
     // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not.
     // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime.
     // Instead, look for this comment, which is almost certainly not in any custom hook.
-    if fs::read_to_string(pre_commit).map_or(false, |contents| {
+    if fs::read_to_string(pre_commit).is_ok_and(|contents| {
         contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
     }) {
-        println!(
+        eprintln!(
             "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
                   Consider moving it to .git/hooks/pre-push instead, which runs less often."
         );
     }
 
     if suggest_setup || changelog_suggestion.is_some() {
-        println!("NOTE: this message was printed twice to make it more likely to be seen");
+        eprintln!("NOTE: this message was printed twice to make it more likely to be seen");
     }
 
     if dump_bootstrap_shims {
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 88595ff7e51..e57ed488f97 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -306,7 +306,7 @@ fn main() {
         // should run on success, after this block.
     }
     if verbose > 0 {
-        println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
+        eprintln!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
     }
 
     if let Some(mut on_fail) = on_fail {
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index d46c0ab7fef..2af2e83db8f 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -287,7 +287,7 @@ impl Step for CodegenBackend {
     fn run(self, builder: &Builder<'_>) {
         // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
         if builder.build.config.vendor && self.backend == "gcc" {
-            println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
+            eprintln!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
             return;
         }
 
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index d857de96cce..61cc9eeed55 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -203,10 +203,8 @@ fn rm_rf(path: &Path) {
 
             do_op(path, "remove dir", |p| match fs::remove_dir(p) {
                 // Check for dir not empty on Windows
-                // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
-                // match on `e.kind()` instead.
                 #[cfg(windows)]
-                Err(e) if e.raw_os_error() == Some(145) => Ok(()),
+                Err(e) if e.kind() == ErrorKind::DirectoryNotEmpty => Ok(()),
                 r => r,
             });
         }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 8e088682f92..93f8091299f 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -330,7 +330,7 @@ fn copy_third_party_objects(
 
     if target == "x86_64-fortanix-unknown-sgx"
         || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
-            && (target.contains("linux") || target.contains("fuchsia"))
+            && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
     {
         let libunwind_path =
             copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
@@ -1611,7 +1611,7 @@ impl Step for Sysroot {
         let sysroot = sysroot_dir(compiler.stage);
 
         builder
-            .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
+            .verbose(|| eprintln!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
         let _ = fs::remove_dir_all(&sysroot);
         t!(fs::create_dir_all(&sysroot));
 
@@ -1655,7 +1655,7 @@ impl Step for Sysroot {
             let mut add_filtered_files = |suffix, contents| {
                 for path in contents {
                     let path = Path::new(&path);
-                    if path.parent().map_or(false, |parent| parent.ends_with(suffix)) {
+                    if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
                         filtered_files.push(path.file_name().unwrap().to_owned());
                     }
                 }
@@ -1681,7 +1681,7 @@ impl Step for Sysroot {
                     return true;
                 }
                 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
-                    builder.verbose_than(1, || println!("ignoring {}", path.display()));
+                    builder.verbose_than(1, || eprintln!("ignoring {}", path.display()));
                     false
                 } else {
                     true
@@ -2240,7 +2240,7 @@ pub fn stream_cargo(
         cargo.arg(arg);
     }
 
-    builder.verbose(|| println!("running: {cargo:?}"));
+    builder.verbose(|| eprintln!("running: {cargo:?}"));
 
     if builder.config.dry_run() {
         return true;
@@ -2266,7 +2266,7 @@ pub fn stream_cargo(
                 cb(msg)
             }
             // If this was informational, just print it out and continue
-            Err(_) => println!("{line}"),
+            Err(_) => eprintln!("{line}"),
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index a636c4a9ef1..57fce206f95 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -549,24 +549,24 @@ impl Step for DebuggerScripts {
             cp_debugger_script("natvis/liballoc.natvis");
             cp_debugger_script("natvis/libcore.natvis");
             cp_debugger_script("natvis/libstd.natvis");
-        } else {
-            cp_debugger_script("rust_types.py");
+        }
 
-            // gdb debugger scripts
-            builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
-            builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
+        cp_debugger_script("rust_types.py");
 
-            cp_debugger_script("gdb_load_rust_pretty_printers.py");
-            cp_debugger_script("gdb_lookup.py");
-            cp_debugger_script("gdb_providers.py");
+        // gdb debugger scripts
+        builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
+        builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
 
-            // lldb debugger scripts
-            builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
+        cp_debugger_script("gdb_load_rust_pretty_printers.py");
+        cp_debugger_script("gdb_lookup.py");
+        cp_debugger_script("gdb_providers.py");
 
-            cp_debugger_script("lldb_lookup.py");
-            cp_debugger_script("lldb_providers.py");
-            cp_debugger_script("lldb_commands")
-        }
+        // lldb debugger scripts
+        builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
+
+        cp_debugger_script("lldb_lookup.py");
+        cp_debugger_script("lldb_providers.py");
+        cp_debugger_script("lldb_commands")
     }
 }
 
@@ -2080,7 +2080,7 @@ fn maybe_install_llvm(
     {
         let mut cmd = command(llvm_config);
         cmd.arg("--libfiles");
-        builder.verbose(|| println!("running {cmd:?}"));
+        builder.verbose(|| eprintln!("running {cmd:?}"));
         let files = cmd.run_capture_stdout(builder).stdout();
         let build_llvm_out = &builder.llvm_out(builder.config.build);
         let target_llvm_out = &builder.llvm_out(target);
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 5ca4321d855..d32e06d8748 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -56,10 +56,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
 fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> {
     let stamp_file = build.out.join("rustfmt.stamp");
 
-    let mut cmd = command(match build.initial_rustfmt() {
-        Some(p) => p,
-        None => return None,
-    });
+    let mut cmd = command(build.initial_rustfmt()?);
     cmd.arg("--version");
 
     let output = cmd.allow_failure().run_capture(build);
@@ -110,10 +107,10 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
         if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
     if len <= 10 {
         for path in paths {
-            println!("fmt: {verb} {adjective}file {path}");
+            eprintln!("fmt: {verb} {adjective}file {path}");
         }
     } else {
-        println!("fmt: {verb} {len} {adjective}files");
+        eprintln!("fmt: {verb} {len} {adjective}files");
     }
 }
 
@@ -202,7 +199,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
                 match get_modified_rs_files(build) {
                     Ok(Some(files)) => {
                         if files.is_empty() {
-                            println!("fmt info: No modified files detected for formatting.");
+                            eprintln!("fmt info: No modified files detected for formatting.");
                             return;
                         }
 
@@ -279,7 +276,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
         Box::new(move |entry| {
             let cwd = std::env::current_dir();
             let entry = t!(entry);
-            if entry.file_type().map_or(false, |t| t.is_file()) {
+            if entry.file_type().is_some_and(|t| t.is_file()) {
                 formatted_paths_ref.lock().unwrap().push({
                     // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter
                     // relative path.
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 0ce86eadbce..b6862c2d5c4 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -21,9 +21,9 @@ const SHELL: &str = "sh";
 
 /// We have to run a few shell scripts, which choke quite a bit on both `\`
 /// characters and on `C:\` paths, so normalize both of them away.
-fn sanitize_sh(path: &Path) -> String {
+fn sanitize_sh(path: &Path, is_cygwin: bool) -> String {
     let path = path.to_str().unwrap().replace('\\', "/");
-    return change_drive(unc_to_lfs(&path)).unwrap_or(path);
+    return if is_cygwin { path } else { change_drive(unc_to_lfs(&path)).unwrap_or(path) };
 
     fn unc_to_lfs(s: &str) -> &str {
         s.strip_prefix("//?/").unwrap_or(s)
@@ -71,6 +71,7 @@ fn install_sh(
     let prefix = default_path(&builder.config.prefix, "/usr/local");
     let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
     let destdir_env = env::var_os("DESTDIR").map(PathBuf::from);
+    let is_cygwin = builder.config.build.is_cygwin();
 
     // Sanity checks on the write access of user.
     //
@@ -103,14 +104,14 @@ fn install_sh(
 
     let mut cmd = command(SHELL);
     cmd.current_dir(&empty_dir)
-        .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
-        .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
-        .arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir)))
-        .arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir)))
-        .arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir)))
-        .arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir)))
-        .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
-        .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
+        .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"), is_cygwin))
+        .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix, is_cygwin)))
+        .arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir, is_cygwin)))
+        .arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir, is_cygwin)))
+        .arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir, is_cygwin)))
+        .arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir, is_cygwin)))
+        .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir, is_cygwin)))
+        .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir, is_cygwin)))
         .arg("--disable-ldconfig");
     cmd.run(builder);
     t!(fs::remove_dir_all(&empty_dir));
@@ -120,7 +121,7 @@ fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
     config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
 }
 
-fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
+fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf, is_cygwin: bool) -> String {
     // The DESTDIR environment variable is a standard way to install software in a subdirectory
     // while keeping the original directory structure, even if the prefix or other directories
     // contain absolute paths.
@@ -146,7 +147,7 @@ fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
         assert!(path.is_absolute(), "could not make the path relative");
     }
 
-    sanitize_sh(&path)
+    sanitize_sh(&path, is_cygwin)
 }
 
 macro_rules! install {
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 704fa46ab1e..175e9982cc1 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -134,7 +134,7 @@ impl Step for Profile {
                     t!(fs::remove_file(path));
                 }
                 _ => {
-                    println!("Exiting.");
+                    eprintln!("Exiting.");
                     crate::exit!(1);
                 }
             }
@@ -184,15 +184,15 @@ pub fn setup(config: &Config, profile: Profile) {
         Profile::Dist => &["dist", "build"],
     };
 
-    println!();
+    eprintln!();
 
-    println!("To get started, try one of the following commands:");
+    eprintln!("To get started, try one of the following commands:");
     for cmd in suggestions {
-        println!("- `x.py {cmd}`");
+        eprintln!("- `x.py {cmd}`");
     }
 
     if profile != Profile::Dist {
-        println!(
+        eprintln!(
             "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
         );
     }
@@ -224,7 +224,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
     t!(fs::write(path, settings));
 
     let include_path = profile.include_path(&config.src);
-    println!("`x.py` will now use the configuration at {}", include_path.display());
+    eprintln!("`x.py` will now use the configuration at {}", include_path.display());
 }
 
 /// Creates a toolchain link for stage1 using `rustup`
@@ -256,7 +256,7 @@ impl Step for Link {
         }
 
         if !rustup_installed(builder) {
-            println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
+            eprintln!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
             return;
         }
 
@@ -296,7 +296,7 @@ fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
     }
 
     if try_link_toolchain(builder, stage_path) {
-        println!(
+        eprintln!(
             "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
         );
     } else {
@@ -321,14 +321,14 @@ fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
                 return false;
             }
             // The toolchain has already been linked.
-            println!(
+            eprintln!(
                 "`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
             );
         }
         None => {
             // In this case, we don't know if the `stage1` toolchain has been linked;
             // but `rustup` failed, so let's not go any further.
-            println!(
+            eprintln!(
                 "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
             );
         }
@@ -389,12 +389,12 @@ pub fn interactive_path() -> io::Result<Profile> {
         input.parse()
     }
 
-    println!("Welcome to the Rust project! What do you want to do with x.py?");
+    eprintln!("Welcome to the Rust project! What do you want to do with x.py?");
     for ((letter, _), profile) in abbrev_all() {
-        println!("{}) {}: {}", letter, profile, profile.purpose());
+        eprintln!("{}) {}: {}", letter, profile, profile.purpose());
     }
     let template = loop {
-        print!(
+        eprint!(
             "Please choose one ({}): ",
             abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
         );
@@ -428,7 +428,7 @@ enum PromptResult {
 fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
     let mut input = String::new();
     loop {
-        print!("{prompt} ");
+        eprint!("{prompt} ");
         io::stdout().flush()?;
         input.clear();
         io::stdin().read_line(&mut input)?;
@@ -452,24 +452,26 @@ pub struct Hook;
 impl Step for Hook {
     type Output = ();
     const DEFAULT: bool = true;
+
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.alias("hook")
     }
+
     fn make_run(run: RunConfig<'_>) {
-        if run.builder.config.dry_run() {
-            return;
-        }
         if let [cmd] = &run.paths[..] {
             if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
                 run.builder.ensure(Hook);
             }
         }
     }
+
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let config = &builder.config;
-        if config.dry_run() {
+
+        if config.dry_run() || !config.rust_info.is_managed_git_subrepository() {
             return;
         }
+
         t!(install_git_hook_maybe(builder, config));
     }
 }
@@ -488,7 +490,7 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
         return Ok(());
     }
 
-    println!(
+    eprintln!(
         "\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
 If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
 pushing your code to ensure your code is up to par. If you decide later that this behavior is
@@ -496,7 +498,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
     );
 
     if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
-        println!("Ok, skipping installation!");
+        eprintln!("Ok, skipping installation!");
         return Ok(());
     }
     if !hooks_dir.exists() {
@@ -513,7 +515,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
             );
             return Err(e);
         }
-        Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
+        Ok(_) => eprintln!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
     };
     Ok(())
 }
@@ -539,7 +541,7 @@ Select which editor you would like to set up [default: None]: ";
 
         let mut input = String::new();
         loop {
-            print!("{}", prompt_str);
+            eprint!("{}", prompt_str);
             io::stdout().flush()?;
             input.clear();
             io::stdin().read_line(&mut input)?;
@@ -572,6 +574,7 @@ Select which editor you would like to set up [default: None]: ";
                 "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
                 "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
                 "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
+                "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
             ],
             EditorKind::Emacs => vec![
                 "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
@@ -653,7 +656,7 @@ impl Step for Editor {
                 if let Some(editor_kind) = editor_kind {
                     while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
                 } else {
-                    println!("Ok, skipping editor setup!");
+                    eprintln!("Ok, skipping editor setup!");
                 }
             }
             Err(e) => eprintln!("Could not determine the editor: {e}"),
@@ -686,7 +689,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             mismatched_settings = Some(false);
         }
     }
-    println!(
+    eprintln!(
         "\nx.py can automatically install the recommended `{settings_filename}` file for rustc development"
     );
 
@@ -705,7 +708,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
         Some(PromptResult::Yes) => true,
         Some(PromptResult::Print) => false,
         _ => {
-            println!("Ok, skipping settings!");
+            eprintln!("Ok, skipping settings!");
             return Ok(true);
         }
     };
@@ -732,9 +735,9 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             _ => "Created",
         };
         fs::write(&settings_path, editor.settings_template())?;
-        println!("{verb} `{}`", settings_filename);
+        eprintln!("{verb} `{}`", settings_filename);
     } else {
-        println!("\n{}", editor.settings_template());
+        eprintln!("\n{}", editor.settings_template());
     }
     Ok(should_create)
 }
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index ba9b1b2fc33..7b2d9fff8f5 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -66,6 +66,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
             build.build();
         }
     } else {
-        println!("HELP: consider using the `--run` flag to automatically run suggested tests");
+        eprintln!("HELP: consider using the `--run` flag to automatically run suggested tests");
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dd967bca867..380626952b2 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -263,12 +263,16 @@ pub struct Cargo {
     host: TargetSelection,
 }
 
+impl Cargo {
+    const CRATE_PATH: &str = "src/tools/cargo";
+}
+
 impl Step for Cargo {
     type Output = ();
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/tools/cargo")
+        run.path(Self::CRATE_PATH)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -286,7 +290,7 @@ impl Step for Cargo {
             Mode::ToolRustc,
             self.host,
             Kind::Test,
-            "src/tools/cargo",
+            Self::CRATE_PATH,
             SourceType::Submodule,
             &[],
         );
@@ -301,6 +305,10 @@ impl Step for Cargo {
         // those features won't be able to land.
         cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
         cargo.env("PATH", path_for_cargo(builder, compiler));
+        // 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`.
+        cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
 
         #[cfg(feature = "build-metrics")]
         builder.metrics.begin_test_suite(
@@ -463,11 +471,11 @@ impl Miri {
         // We re-use the `cargo` from above.
         cargo.arg("--print-sysroot");
 
-        builder.verbose(|| println!("running: {cargo:?}"));
+        builder.verbose(|| eprintln!("running: {cargo:?}"));
         let stdout = cargo.run_capture_stdout(builder).stdout();
         // Output is "<sysroot>\n".
         let sysroot = stdout.trim_end();
-        builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
+        builder.verbose(|| eprintln!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
         PathBuf::from(sysroot)
     }
 }
@@ -1062,23 +1070,33 @@ impl Step for Tidy {
         }
 
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
-            builder.info("fmt check");
-            if builder.initial_rustfmt().is_none() {
-                let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap();
-                eprintln!(
-                    "\
+            if !builder.config.json_output {
+                builder.info("fmt check");
+                if builder.initial_rustfmt().is_none() {
+                    let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
+                    eprintln!(
+                        "\
 ERROR: no `rustfmt` binary found in {PATH}
 INFO: `rust.channel` is currently set to \"{CHAN}\"
 HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file
 HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
-                    PATH = inferred_rustfmt_dir.display(),
-                    CHAN = builder.config.channel,
+                        PATH = inferred_rustfmt_dir.display(),
+                        CHAN = builder.config.channel,
+                    );
+                    crate::exit!(1);
+                }
+                let all = false;
+                crate::core::build_steps::format::format(
+                    builder,
+                    !builder.config.cmd.bless(),
+                    all,
+                    &[],
+                );
+            } else {
+                eprintln!(
+                    "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
                 );
-                crate::exit!(1);
             }
-            let all = false;
-            crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), all, &[
-            ]);
         }
 
         builder.info("tidy check");
@@ -2470,7 +2488,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
         }
     }
 
-    builder.verbose(|| println!("doc tests for: {}", markdown.display()));
+    builder.verbose(|| eprintln!("doc tests for: {}", markdown.display()));
     let mut cmd = builder.rustdoc_cmd(compiler);
     builder.add_rust_test_threads(&mut cmd);
     // allow for unstable options such as new editions
@@ -2616,6 +2634,11 @@ fn prepare_cargo_test(
     if builder.kind == Kind::Test && !builder.fail_fast {
         cargo.arg("--no-fail-fast");
     }
+
+    if builder.config.json_output {
+        cargo.arg("--message-format=json");
+    }
+
     match builder.doc_tests {
         DocTests::Only => {
             cargo.arg("--doc");
@@ -2748,6 +2771,10 @@ impl Step for Crate {
             // `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
             // instead. But crucially we only do that for the library, not the test builds.
             cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
+            // std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
+            // does not set this directly, but relies on the rustc wrapper to set it, and we are not using
+            // the wrapper -- hence we have to set it ourselves.
+            cargo.rustflag("-Zforce-unstable-if-unmarked");
             cargo
         } else {
             // Also prepare a sysroot for the target.
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 0688a1d6892..38abca8b8da 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -523,7 +523,7 @@ impl Builder<'_> {
 
         let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
         if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) {
-            println!("using sysroot {sysroot_str}");
+            eprintln!("using sysroot {sysroot_str}");
         }
 
         let mut rustflags = Rustflags::new(target);
@@ -703,6 +703,9 @@ impl Builder<'_> {
 
         cargo.arg("-j").arg(self.jobs().to_string());
 
+        // Make cargo emit diagnostics relative to the rustc src dir.
+        cargo.arg(format!("-Zroot-dir={}", self.src.display()));
+
         // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
         // Force cargo to output binaries with disambiguating hashes in the name
         let mut metadata = if compiler.stage == 0 {
@@ -1030,6 +1033,15 @@ impl Builder<'_> {
 
         if mode == Mode::Rustc {
             rustflags.arg("-Wrustc::internal");
+            // cfg(bootstrap) - remove this check when lint is in bootstrap compiler
+            if stage != 0 {
+                // Lint is allow by default so downstream tools don't get a lit
+                // they can do nothing about
+                // We shouldn't be preinterning symbols used by tests
+                if cmd_kind != Kind::Test {
+                    rustflags.arg("-Drustc::symbol_intern_string_literal");
+                }
+            }
             // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
             // of the individual lints are satisfied.
             rustflags.arg("-Wkeyword_idents_2024");
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 945a7b7366f..ffe3e053e72 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -258,11 +258,11 @@ impl PathSet {
 
     // internal use only
     fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool {
-        if let Some(p_kind) = &p.kind {
-            p.path.ends_with(needle) && *p_kind == module
-        } else {
-            p.path.ends_with(needle)
-        }
+        let check_path = || {
+            // This order is important for retro-compatibility, as `starts_with` was introduced later.
+            p.path.ends_with(needle) || p.path.starts_with(needle)
+        };
+        if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() }
     }
 
     /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the
@@ -392,14 +392,14 @@ impl StepDescription {
     fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
         if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
             if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
-                println!("Skipping {pathset:?} because it is excluded");
+                eprintln!("Skipping {pathset:?} because it is excluded");
             }
             return true;
         }
 
         if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
             builder.verbose(|| {
-                println!(
+                eprintln!(
                     "{:?} not skipped for {:?} -- not in {:?}",
                     pathset, self.name, builder.config.skip
                 )
@@ -765,6 +765,54 @@ impl Kind {
     }
 }
 
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+struct Libdir {
+    compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl Step for Libdir {
+    type Output = PathBuf;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never()
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler);
+        let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib");
+
+        if !builder.config.dry_run() {
+            // Avoid deleting the `rustlib/` directory we just copied (in `impl Step for
+            // Sysroot`).
+            if !builder.download_rustc() {
+                let sysroot_target_libdir = sysroot.join(self.target).join("lib");
+                builder.verbose(|| {
+                    eprintln!(
+                        "Removing sysroot {} to avoid caching bugs",
+                        sysroot_target_libdir.display()
+                    )
+                });
+                let _ = fs::remove_dir_all(&sysroot_target_libdir);
+                t!(fs::create_dir_all(&sysroot_target_libdir));
+            }
+
+            if self.compiler.stage == 0 {
+                // The stage 0 compiler for the build triple is always pre-built. Ensure that
+                // `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use
+                // it when run.
+                dist::maybe_install_llvm_target(
+                    builder,
+                    self.compiler.host,
+                    &builder.sysroot(self.compiler),
+                );
+            }
+        }
+
+        sysroot
+    }
+}
+
 impl<'a> Builder<'a> {
     fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
         macro_rules! describe {
@@ -1165,56 +1213,13 @@ impl<'a> Builder<'a> {
 
     /// Returns the bindir for a compiler's sysroot.
     pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
-        self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin")
+        self.ensure(Libdir { compiler, target }).join(target).join("bin")
     }
 
     /// Returns the libdir where the standard library and other artifacts are
     /// found for a compiler's sysroot.
     pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
-        #[derive(Debug, Clone, Hash, PartialEq, Eq)]
-        struct Libdir {
-            compiler: Compiler,
-            target: TargetSelection,
-        }
-        impl Step for Libdir {
-            type Output = PathBuf;
-
-            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-                run.never()
-            }
-
-            fn run(self, builder: &Builder<'_>) -> PathBuf {
-                let lib = builder.sysroot_libdir_relative(self.compiler);
-                let sysroot = builder
-                    .sysroot(self.compiler)
-                    .join(lib)
-                    .join("rustlib")
-                    .join(self.target)
-                    .join("lib");
-                // Avoid deleting the rustlib/ directory we just copied
-                // (in `impl Step for Sysroot`).
-                if !builder.download_rustc() {
-                    builder.verbose(|| {
-                        println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
-                    });
-                    let _ = fs::remove_dir_all(&sysroot);
-                    t!(fs::create_dir_all(&sysroot));
-                }
-
-                if self.compiler.stage == 0 {
-                    // The stage 0 compiler for the build triple is always pre-built.
-                    // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run.
-                    dist::maybe_install_llvm_target(
-                        builder,
-                        self.compiler.host,
-                        &builder.sysroot(self.compiler),
-                    );
-                }
-
-                sysroot
-            }
-        }
-        self.ensure(Libdir { compiler, target })
+        self.ensure(Libdir { compiler, target }).join(target).join("lib")
     }
 
     pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
@@ -1262,7 +1267,7 @@ impl<'a> Builder<'a> {
     pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
         match self.config.libdir_relative() {
             Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
-            _ if compiler.stage == 0 => &self.build.initial_libdir,
+            _ if compiler.stage == 0 => &self.build.initial_relative_libdir,
             _ => Path::new("lib"),
         }
     }
@@ -1432,11 +1437,11 @@ impl<'a> Builder<'a> {
                 panic!("{}", out);
             }
             if let Some(out) = self.cache.get(&step) {
-                self.verbose_than(1, || println!("{}c {:?}", "  ".repeat(stack.len()), step));
+                self.verbose_than(1, || eprintln!("{}c {:?}", "  ".repeat(stack.len()), step));
 
                 return out;
             }
-            self.verbose_than(1, || println!("{}> {:?}", "  ".repeat(stack.len()), step));
+            self.verbose_than(1, || eprintln!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
 
@@ -1457,7 +1462,7 @@ impl<'a> Builder<'a> {
             let step_string = format!("{step:?}");
             let brace_index = step_string.find('{').unwrap_or(0);
             let type_string = type_name::<S>();
-            println!(
+            eprintln!(
                 "[TIMING] {} {} -- {}.{:03}",
                 &type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
                 &step_string[brace_index..],
@@ -1474,7 +1479,9 @@ impl<'a> Builder<'a> {
             let cur_step = stack.pop().expect("step stack empty");
             assert_eq!(cur_step.downcast_ref(), Some(&step));
         }
-        self.verbose_than(1, || println!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step));
+        self.verbose_than(1, || {
+            eprintln!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step)
+        });
         self.cache.put(step, out.clone());
         out
     }
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index a1c8bff0db9..b2ffbd9c70f 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -738,3 +738,49 @@ mod dist {
         ]);
     }
 }
+
+mod sysroot_target_dirs {
+    use super::{
+        Build, Builder, Compiler, TEST_TRIPLE_1, TEST_TRIPLE_2, TargetSelection, configure,
+    };
+
+    #[test]
+    fn test_sysroot_target_libdir() {
+        let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
+        let builder = Builder::new(&build);
+        let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
+        let compiler = Compiler { stage: 1, host: target_triple_1 };
+        let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
+        let actual = builder.sysroot_target_libdir(compiler, target_triple_2);
+
+        assert_eq!(
+            builder
+                .sysroot(compiler)
+                .join(builder.sysroot_libdir_relative(compiler))
+                .join("rustlib")
+                .join(TEST_TRIPLE_2)
+                .join("lib"),
+            actual
+        );
+    }
+
+    #[test]
+    fn test_sysroot_target_bindir() {
+        let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
+        let builder = Builder::new(&build);
+        let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
+        let compiler = Compiler { stage: 1, host: target_triple_1 };
+        let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
+        let actual = builder.sysroot_target_bindir(compiler, target_triple_2);
+
+        assert_eq!(
+            builder
+                .sysroot(compiler)
+                .join(builder.sysroot_libdir_relative(compiler))
+                .join("rustlib")
+                .join(TEST_TRIPLE_2)
+                .join("bin"),
+            actual
+        );
+    }
+}
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 9b2d49e7620..002b990bb52 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -379,6 +379,7 @@ pub struct Config {
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
     pub initial_cargo_clippy: Option<PathBuf>,
+    pub initial_sysroot: PathBuf,
 
     #[cfg(not(test))]
     initial_rustfmt: RefCell<RustfmtState>,
@@ -564,6 +565,12 @@ impl TargetSelection {
         self.ends_with("windows-gnu")
     }
 
+    pub fn is_cygwin(&self) -> bool {
+        self.is_windows() &&
+        // ref. https://cygwin.com/pipermail/cygwin/2022-February/250802.html
+        env::var("OSTYPE").is_ok_and(|v| v.to_lowercase().contains("cygwin"))
+    }
+
     /// Path to the file defining the custom target, if any.
     pub fn filepath(&self) -> Option<&Path> {
         self.file.as_ref().map(Path::new)
@@ -1292,7 +1299,7 @@ impl Config {
                     .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
                 {
                     if !changes.is_empty() {
-                        println!(
+                        eprintln!(
                             "WARNING: There have been changes to x.py since you last updated:\n{}",
                             crate::human_readable_changes(&changes)
                         );
@@ -1558,13 +1565,11 @@ impl Config {
         }
 
         if cargo_clippy.is_some() && rustc.is_none() {
-            println!(
+            eprintln!(
                 "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
             );
         }
 
-        config.initial_cargo_clippy = cargo_clippy;
-
         config.initial_rustc = if let Some(rustc) = rustc {
             if !flags.skip_stage0_validation {
                 config.check_stage0_version(&rustc, "rustc");
@@ -1580,6 +1585,10 @@ impl Config {
                 .join(exe("rustc", config.build))
         };
 
+        config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
+
+        config.initial_cargo_clippy = cargo_clippy;
+
         config.initial_cargo = if let Some(cargo) = cargo {
             if !flags.skip_stage0_validation {
                 config.check_stage0_version(&cargo, "cargo");
@@ -1587,12 +1596,7 @@ impl Config {
             cargo
         } else {
             config.download_beta_toolchain();
-            config
-                .out
-                .join(config.build)
-                .join("stage0")
-                .join("bin")
-                .join(exe("cargo", config.build))
+            config.initial_sysroot.join("bin").join(exe("cargo", config.build))
         };
 
         // NOTE: it's important this comes *after* we set `initial_rustc` just above.
@@ -1634,7 +1638,6 @@ impl Config {
         set(&mut config.docs_minification, docs_minification);
         set(&mut config.docs, docs);
         set(&mut config.locked_deps, locked_deps);
-        set(&mut config.vendor, vendor);
         set(&mut config.full_bootstrap, full_bootstrap);
         set(&mut config.extended, extended);
         config.tools = tools;
@@ -1665,7 +1668,7 @@ impl Config {
         }
 
         config.llvm_assertions =
-            toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false));
+            toml.llvm.as_ref().is_some_and(|llvm| llvm.assertions.unwrap_or(false));
 
         // Store off these values as options because if they're not provided
         // we'll infer default values for them later
@@ -1713,6 +1716,12 @@ impl Config {
         config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
         config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
 
+        config.vendor = vendor.unwrap_or(
+            config.rust_info.is_from_tarball()
+                && config.src.join("vendor").exists()
+                && config.src.join(".cargo/config.toml").exists(),
+        );
+
         if let Some(rust) = toml.rust {
             let Rust {
                 optimize: optimize_toml,
@@ -1843,7 +1852,7 @@ impl Config {
 
             // FIXME: Remove this option at the end of 2024.
             if parallel_compiler.is_some() {
-                println!(
+                eprintln!(
                     "WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default"
                 );
             }
@@ -1875,7 +1884,7 @@ impl Config {
                         if available_backends.contains(&backend) {
                             panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
                         } else {
-                            println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
+                            eprintln!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
                                 Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                 In this case, it would be referred to as '{backend}'.");
                         }
@@ -1904,7 +1913,7 @@ impl Config {
         // tests may fail due to using a different channel than the one used by the compiler during tests.
         if let Some(commit) = &config.download_rustc_commit {
             if is_user_configured_rust_channel {
-                println!(
+                eprintln!(
                     "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
                 );
 
@@ -1994,10 +2003,10 @@ impl Config {
 
             if config.llvm_from_ci {
                 let warn = |option: &str| {
-                    println!(
+                    eprintln!(
                         "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
                     );
-                    println!(
+                    eprintln!(
                         "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
                     );
                 };
@@ -2016,12 +2025,12 @@ impl Config {
                 // if they've chosen a different value.
 
                 if libzstd.is_some() {
-                    println!(
+                    eprintln!(
                         "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!(
+                    eprintln!(
                         "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
                     );
                 }
@@ -2090,7 +2099,7 @@ impl Config {
                             if available_backends.contains(&backend) {
                                 panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
                             } else {
-                                println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
+                                eprintln!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
                                     Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                     In this case, it would be referred to as '{backend}'.");
                             }
@@ -2306,7 +2315,7 @@ impl Config {
         if self.dry_run() {
             return Ok(());
         }
-        self.verbose(|| println!("running: {cmd:?}"));
+        self.verbose(|| eprintln!("running: {cmd:?}"));
         build_helper::util::try_run(cmd, self.is_verbose())
     }
 
@@ -2481,7 +2490,7 @@ impl Config {
                         // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error
                         // to not break CI. For non-CI environments, we should return an error.
                         if CiEnv::is_ci() {
-                            println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
+                            eprintln!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
                             return None;
                         } else {
                             panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");
@@ -2492,8 +2501,8 @@ impl Config {
                         let ci_config_toml = match self.get_builder_toml("ci-rustc") {
                             Ok(ci_config_toml) => ci_config_toml,
                             Err(e) if e.to_string().contains("unknown field") => {
-                                println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
-                                println!("HELP: Consider rebasing to a newer commit if available.");
+                                eprintln!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
+                                eprintln!("HELP: Consider rebasing to a newer commit if available.");
                                 return None;
                             },
                             Err(e) => {
@@ -2507,6 +2516,7 @@ impl Config {
                         // Check the config compatibility
                         // FIXME: this doesn't cover `--set` flags yet.
                         let res = check_incompatible_options_for_ci_rustc(
+                            self.build,
                             current_config_toml,
                             ci_config_toml,
                         );
@@ -2517,7 +2527,7 @@ impl Config {
                             .is_some_and(|s| s == "1" || s == "true");
 
                         if disable_ci_rustc_if_incompatible && res.is_err() {
-                            println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
+                            eprintln!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
                             return None;
                         }
 
@@ -2702,7 +2712,7 @@ impl Config {
             return;
         }
 
-        println!("Updating submodule {relative_path}");
+        eprintln!("Updating submodule {relative_path}");
         self.check_run(
             helpers::git(Some(&self.src))
                 .run_always()
@@ -2825,7 +2835,7 @@ impl Config {
             Some(StringOrBool::Bool(true)) => false,
             Some(StringOrBool::String(s)) if s == "if-unchanged" => {
                 if !self.rust_info.is_managed_git_subrepository() {
-                    println!(
+                    eprintln!(
                         "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
                     );
                     crate::exit!(1);
@@ -2858,10 +2868,10 @@ impl Config {
                 if if_unchanged {
                     return None;
                 }
-                println!("ERROR: could not find commit hash for downloading rustc");
-                println!("HELP: maybe your repository history is too shallow?");
-                println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
-                println!("HELP: or fetch enough history to include one upstream commit");
+                eprintln!("ERROR: could not find commit hash for downloading rustc");
+                eprintln!("HELP: maybe your repository history is too shallow?");
+                eprintln!("HELP: consider setting `rust.download-rustc=false` in config.toml");
+                eprintln!("HELP: or fetch enough history to include one upstream commit");
                 crate::exit!(1);
             }
         };
@@ -2900,7 +2910,7 @@ impl Config {
         let if_unchanged = || {
             if self.rust_info.is_from_tarball() {
                 // Git is needed for running "if-unchanged" logic.
-                println!(
+                eprintln!(
                     "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
                 );
                 return false;
@@ -2949,10 +2959,10 @@ impl Config {
         // Only commits merged by bors will have CI artifacts.
         let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
         if commit.is_empty() {
-            println!("error: could not find commit hash for downloading components from CI");
-            println!("help: maybe your repository history is too shallow?");
-            println!("help: consider disabling `{option_name}`");
-            println!("help: or fetch enough history to include one upstream commit");
+            eprintln!("error: could not find commit hash for downloading components from CI");
+            eprintln!("help: maybe your repository history is too shallow?");
+            eprintln!("help: consider disabling `{option_name}`");
+            eprintln!("help: or fetch enough history to include one upstream commit");
             crate::exit!(1);
         }
 
@@ -2964,14 +2974,14 @@ impl Config {
         if has_changes {
             if if_unchanged {
                 if self.is_verbose() {
-                    println!(
+                    eprintln!(
                         "warning: saw changes to one of {modified_paths:?} since {commit}; \
                             ignoring `{option_name}`"
                     );
                 }
                 return None;
             }
-            println!(
+            eprintln!(
                 "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
             );
         }
@@ -3008,7 +3018,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
         ($current:expr, $expected:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    println!(
+                    eprintln!(
                         "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
                         stringify!($expected).replace("_", "-"),
@@ -3088,17 +3098,18 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
 /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
 /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
 fn check_incompatible_options_for_ci_rustc(
+    host: TargetSelection,
     current_config_toml: TomlConfig,
     ci_config_toml: TomlConfig,
 ) -> Result<(), String> {
     macro_rules! err {
-        ($current:expr, $expected:expr) => {
+        ($current:expr, $expected:expr, $config_section:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
                     return Err(format!(
-                        "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \
+                        "ERROR: Setting `{}` is incompatible with `rust.download-rustc`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
-                        stringify!($expected).replace("_", "-"),
+                        format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
                         $current,
                         if $expected.is_some() { "None/" } else { "" },
                         $expected,
@@ -3109,13 +3120,13 @@ fn check_incompatible_options_for_ci_rustc(
     }
 
     macro_rules! warn {
-        ($current:expr, $expected:expr) => {
+        ($current:expr, $expected:expr, $config_section:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    println!(
-                        "WARNING: `rust.{}` has no effect with `rust.download-rustc`. \
+                    eprintln!(
+                        "WARNING: `{}` has no effect with `rust.download-rustc`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
-                        stringify!($expected).replace("_", "-"),
+                        format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
                         $current,
                         if $expected.is_some() { "None/" } else { "" },
                         $expected,
@@ -3125,6 +3136,31 @@ fn check_incompatible_options_for_ci_rustc(
         };
     }
 
+    let current_profiler = current_config_toml.build.as_ref().and_then(|b| b.profiler);
+    let profiler = ci_config_toml.build.as_ref().and_then(|b| b.profiler);
+    err!(current_profiler, profiler, "build");
+
+    let current_optimized_compiler_builtins =
+        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+    let optimized_compiler_builtins =
+        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+    err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
+
+    // We always build the in-tree compiler on cross targets, so we only care
+    // about the host target here.
+    let host_str = host.to_string();
+    if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) {
+        if current_cfg.profiler.is_some() {
+            let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str));
+            let ci_cfg = ci_target_toml.ok_or(format!(
+                "Target specific config for '{host_str}' is not present for CI-rustc"
+            ))?;
+
+            let profiler = &ci_cfg.profiler;
+            err!(current_cfg.profiler, profiler, "build");
+        }
+    }
+
     let (Some(current_rust_config), Some(ci_rust_config)) =
         (current_config_toml.rust, ci_config_toml.rust)
     else {
@@ -3198,24 +3234,24 @@ fn check_incompatible_options_for_ci_rustc(
     // If the option belongs to the first category, we call `err` macro for a hard error;
     // otherwise, we just print a warning with `warn` macro.
 
-    err!(current_rust_config.optimize, optimize);
-    err!(current_rust_config.randomize_layout, randomize_layout);
-    err!(current_rust_config.debug_logging, debug_logging);
-    err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc);
-    err!(current_rust_config.rpath, rpath);
-    err!(current_rust_config.strip, strip);
-    err!(current_rust_config.lld_mode, lld_mode);
-    err!(current_rust_config.llvm_tools, llvm_tools);
-    err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker);
-    err!(current_rust_config.jemalloc, jemalloc);
-    err!(current_rust_config.default_linker, default_linker);
-    err!(current_rust_config.stack_protector, stack_protector);
-    err!(current_rust_config.lto, lto);
-    err!(current_rust_config.std_features, std_features);
-
-    warn!(current_rust_config.channel, channel);
-    warn!(current_rust_config.description, description);
-    warn!(current_rust_config.incremental, incremental);
+    err!(current_rust_config.optimize, optimize, "rust");
+    err!(current_rust_config.randomize_layout, randomize_layout, "rust");
+    err!(current_rust_config.debug_logging, debug_logging, "rust");
+    err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust");
+    err!(current_rust_config.rpath, rpath, "rust");
+    err!(current_rust_config.strip, strip, "rust");
+    err!(current_rust_config.lld_mode, lld_mode, "rust");
+    err!(current_rust_config.llvm_tools, llvm_tools, "rust");
+    err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust");
+    err!(current_rust_config.jemalloc, jemalloc, "rust");
+    err!(current_rust_config.default_linker, default_linker, "rust");
+    err!(current_rust_config.stack_protector, stack_protector, "rust");
+    err!(current_rust_config.lto, lto, "rust");
+    err!(current_rust_config.std_features, std_features, "rust");
+
+    warn!(current_rust_config.channel, channel, "rust");
+    warn!(current_rust_config.description, description, "rust");
+    warn!(current_rust_config.incremental, incremental, "rust");
 
     Ok(())
 }
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index bfeb811508c..66b9f5ed84e 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -196,12 +196,12 @@ impl Flags {
         if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
             HelpVerboseOnly::try_parse_from(normalize_args(args))
         {
-            println!("NOTE: updating submodules before printing available paths");
+            eprintln!("NOTE: updating submodules before printing available paths");
             let config = Config::parse(Self::parse(&[String::from("build")]));
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
             if let Some(s) = paths {
-                println!("{s}");
+                eprintln!("{s}");
             } else {
                 panic!("No paths available for subcommand `{}`", subcommand.as_str());
             }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index db1f5b08338..05b91c518cf 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -77,7 +77,7 @@ impl Config {
         if self.dry_run() && !cmd.run_always {
             return true;
         }
-        self.verbose(|| println!("running: {cmd:?}"));
+        self.verbose(|| eprintln!("running: {cmd:?}"));
         check_run(cmd, self.is_verbose())
     }
 
@@ -144,7 +144,7 @@ impl Config {
     /// Please see <https://nixos.org/patchelf.html> for more information
     fn fix_bin_or_dylib(&self, fname: &Path) {
         assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
-        println!("attempting to patch {}", fname.display());
+        eprintln!("attempting to patch {}", fname.display());
 
         // Only build `.nix-deps` once.
         static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new();
@@ -206,7 +206,7 @@ impl Config {
     }
 
     fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
-        self.verbose(|| println!("download {url}"));
+        self.verbose(|| eprintln!("download {url}"));
         // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
         let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
         // While bootstrap itself only supports http and https downloads, downstream forks might
@@ -226,7 +226,7 @@ impl Config {
     }
 
     fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
-        println!("downloading {url}");
+        eprintln!("downloading {url}");
         // Try curl. If that fails and we are on windows, fallback to PowerShell.
         // options should be kept in sync with
         // src/bootstrap/src/core/download.rs
@@ -341,7 +341,7 @@ impl Config {
             short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
             let dst_path = dst.join(short_path);
             self.verbose(|| {
-                println!("extracting {} to {}", original_path.display(), dst.display())
+                eprintln!("extracting {} to {}", original_path.display(), dst.display())
             });
             if !t!(member.unpack_in(dst)) {
                 panic!("path traversal attack ??");
@@ -365,7 +365,7 @@ impl Config {
     pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
         use sha2::Digest;
 
-        self.verbose(|| println!("verifying {}", path.display()));
+        self.verbose(|| eprintln!("verifying {}", path.display()));
 
         if self.dry_run() {
             return false;
@@ -391,7 +391,7 @@ impl Config {
         let verified = checksum == expected;
 
         if !verified {
-            println!(
+            eprintln!(
                 "invalid checksum: \n\
                 found:    {checksum}\n\
                 expected: {expected}",
@@ -421,15 +421,14 @@ enum DownloadSource {
 /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
 impl Config {
     pub(crate) fn download_clippy(&self) -> PathBuf {
-        self.verbose(|| println!("downloading stage0 clippy artifacts"));
+        self.verbose(|| eprintln!("downloading stage0 clippy artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
         let host = self.build;
 
-        let bin_root = self.out.join(host).join("stage0");
-        let clippy_stamp = bin_root.join(".clippy-stamp");
-        let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host));
+        let clippy_stamp = self.initial_sysroot.join(".clippy-stamp");
+        let cargo_clippy = self.initial_sysroot.join("bin").join(exe("cargo-clippy", host));
         if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) {
             return cargo_clippy;
         }
@@ -519,7 +518,7 @@ impl Config {
     }
 
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
-        self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
+        self.verbose(|| eprintln!("using downloaded stage2 artifacts from CI (commit {commit})"));
 
         let version = self.artifact_version_part(commit);
         // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@@ -540,7 +539,7 @@ impl Config {
 
     #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn download_beta_toolchain(&self) {
-        self.verbose(|| println!("downloading stage0 beta artifacts"));
+        self.verbose(|| eprintln!("downloading stage0 beta artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
@@ -678,7 +677,7 @@ impl Config {
                     return;
                 } else {
                     self.verbose(|| {
-                        println!(
+                        eprintln!(
                             "ignoring cached file {} due to failed verification",
                             tarball.display()
                         )
@@ -777,10 +776,10 @@ download-rustc = false
                     t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
                 }
                 Err(e) if e.to_string().contains("unknown field") => {
-                    println!(
+                    eprintln!(
                         "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
                     );
-                    println!("HELP: Consider rebasing to a newer commit if available.");
+                    eprintln!("HELP: Consider rebasing to a newer commit if available.");
                 }
                 Err(e) => {
                     eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
@@ -830,7 +829,7 @@ download-rustc = false
 
 fn path_is_dylib(path: &Path) -> bool {
     // The .so is not necessarily the extension, it might be libLLVM.so.18.1
-    path.to_str().map_or(false, |path| path.contains(".so"))
+    path.to_str().is_some_and(|path| path.contains(".so"))
 }
 
 /// Checks whether the CI rustc is available for the given target triple.
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index fabb4f2b13b..71e7f40f032 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -135,19 +135,15 @@ pub fn check(build: &mut Build) {
 
     // We need cmake, but only if we're actually building LLVM or sanitizers.
     let building_llvm = !build.config.llvm_from_ci
-        && build
-            .hosts
-            .iter()
-            .map(|host| {
-                build.config.llvm_enabled(*host)
-                    && build
-                        .config
-                        .target_config
-                        .get(host)
-                        .map(|config| config.llvm_config.is_none())
-                        .unwrap_or(true)
-            })
-            .any(|build_llvm_ourselves| build_llvm_ourselves);
+        && build.hosts.iter().any(|host| {
+            build.config.llvm_enabled(*host)
+                && build
+                    .config
+                    .target_config
+                    .get(host)
+                    .map(|config| config.llvm_config.is_none())
+                    .unwrap_or(true)
+        });
 
     let need_cmake = building_llvm || build.config.any_sanitizers_to_build();
     if need_cmake && cmd_finder.maybe_have("cmake").is_none() {
@@ -241,11 +237,11 @@ than building it.
                 stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
 
             if !duplicated_targets.is_empty() {
-                println!(
+                eprintln!(
                     "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
                 );
                 for duplicated_target in duplicated_targets {
-                    println!("  {duplicated_target}");
+                    eprintln!("  {duplicated_target}");
                 }
                 std::process::exit(1);
             }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index c384fd6bf43..5f778223d7d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -158,7 +158,7 @@ pub struct Build {
     initial_rustc: PathBuf,
     initial_cargo: PathBuf,
     initial_lld: PathBuf,
-    initial_libdir: PathBuf,
+    initial_relative_libdir: PathBuf,
     initial_sysroot: PathBuf,
 
     // Runtime state filled in later on
@@ -312,46 +312,19 @@ impl Build {
         let in_tree_llvm_info = config.in_tree_llvm_info.clone();
         let in_tree_gcc_info = config.in_tree_gcc_info.clone();
 
-        let initial_target_libdir_str = if config.dry_run() {
-            "/dummy/lib/path/to/lib/".to_string()
-        } else {
-            output(
-                Command::new(&config.initial_rustc)
-                    .arg("--target")
-                    .arg(config.build.rustc_target_arg())
-                    .arg("--print")
-                    .arg("target-libdir"),
-            )
-        };
+        let initial_target_libdir_str =
+            config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib");
+
         let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap();
         let initial_lld = initial_target_dir.join("bin").join("rust-lld");
 
-        let initial_sysroot = if config.dry_run() {
-            "/dummy".to_string()
-        } else {
-            output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot"))
-        }
-        .trim()
-        .to_string();
-
-        // FIXME(Zalathar): Determining this path occasionally fails locally for
-        // unknown reasons, so we print some extra context to help track down why.
-        let find_initial_libdir = || {
-            let initial_libdir =
-                initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?;
-            Some(initial_libdir.to_path_buf())
-        };
-        let Some(initial_libdir) = find_initial_libdir() else {
-            panic!(
-                "couldn't determine `initial_libdir`:
-- config.initial_rustc:      {rustc:?}
-- initial_target_libdir_str: {initial_target_libdir_str:?}
-- initial_target_dir:        {initial_target_dir:?}
-- initial_sysroot:           {initial_sysroot:?}
-",
-                rustc = config.initial_rustc,
-            );
-        };
+        let initial_relative_libdir = initial_target_dir
+            .ancestors()
+            .nth(2)
+            .unwrap()
+            .strip_prefix(&config.initial_sysroot)
+            .expect("Couldn’t determine initial relative libdir.")
+            .to_path_buf();
 
         let version = std::fs::read_to_string(src.join("src").join("version"))
             .expect("failed to read src/version");
@@ -380,11 +353,11 @@ impl Build {
         }
 
         let mut build = Build {
+            initial_lld,
+            initial_relative_libdir,
             initial_rustc: config.initial_rustc.clone(),
             initial_cargo: config.initial_cargo.clone(),
-            initial_lld,
-            initial_libdir,
-            initial_sysroot: initial_sysroot.into(),
+            initial_sysroot: config.initial_sysroot.clone(),
             local_rebuild: config.local_rebuild,
             fail_fast: config.cmd.fail_fast(),
             doc_tests: config.cmd.doc_tests(),
@@ -433,11 +406,11 @@ impl Build {
             .unwrap()
             .trim();
         if local_release.split('.').take(2).eq(version.split('.').take(2)) {
-            build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
+            build.verbose(|| eprintln!("auto-detected local-rebuild {local_release}"));
             build.local_rebuild = true;
         }
 
-        build.verbose(|| println!("finding compilers"));
+        build.verbose(|| eprintln!("finding compilers"));
         utils::cc_detect::find(&build);
         // When running `setup`, the profile is about to change, so any requirements we have now may
         // be different on the next invocation. Don't check for them until the next time x.py is
@@ -445,7 +418,7 @@ impl Build {
         //
         // Similarly, for `setup` we don't actually need submodules or cargo metadata.
         if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
-            build.verbose(|| println!("running sanity check"));
+            build.verbose(|| eprintln!("running sanity check"));
             crate::core::sanity::check(&mut build);
 
             // Make sure we update these before gathering metadata so we don't get an error about missing
@@ -463,7 +436,7 @@ impl Build {
             // Now, update all existing submodules.
             build.update_existing_submodules();
 
-            build.verbose(|| println!("learning about cargo"));
+            build.verbose(|| eprintln!("learning about cargo"));
             crate::core::metadata::build(&mut build);
         }
 
@@ -632,7 +605,7 @@ impl Build {
         let stamp = dir.join(".stamp");
         let mut cleared = false;
         if mtime(&stamp) < mtime(input) {
-            self.verbose(|| println!("Dirty - {}", dir.display()));
+            self.verbose(|| eprintln!("Dirty - {}", dir.display()));
             let _ = fs::remove_dir_all(dir);
             cleared = true;
         } else if stamp.exists() {
@@ -917,7 +890,7 @@ impl Build {
         let executed_at = std::panic::Location::caller();
 
         self.verbose(|| {
-            println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
+            eprintln!("running: {command:?} (created at {created_at}, executed at {executed_at})")
         });
 
         let cmd = command.as_command_mut();
@@ -974,7 +947,7 @@ Executed at: {executed_at}"#,
 
         let fail = |message: &str, output: CommandOutput| -> ! {
             if self.is_verbose() {
-                println!("{message}");
+                eprintln!("{message}");
             } else {
                 let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
                 // If the command captures output, the user would not see any indication that
@@ -984,16 +957,16 @@ Executed at: {executed_at}"#,
                     if let Some(stdout) =
                         output.stdout_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        println!("STDOUT:\n{stdout}\n");
+                        eprintln!("STDOUT:\n{stdout}\n");
                     }
                     if let Some(stderr) =
                         output.stderr_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        println!("STDERR:\n{stderr}\n");
+                        eprintln!("STDERR:\n{stderr}\n");
                     }
-                    println!("Command {command:?} has failed. Rerun with -v to see more details.");
+                    eprintln!("Command {command:?} has failed. Rerun with -v to see more details.");
                 } else {
-                    println!("Command has failed. Rerun with -v to see more details.");
+                    eprintln!("Command has failed. Rerun with -v to see more details.");
                 }
             }
             exit!(1);
@@ -1038,7 +1011,7 @@ Executed at: {executed_at}"#,
         match self.config.dry_run {
             DryRun::SelfCheck => (),
             DryRun::Disabled | DryRun::UserSelected => {
-                println!("{msg}");
+                eprintln!("{msg}");
             }
         }
     }
@@ -1693,7 +1666,7 @@ Executed at: {executed_at}"#,
         if self.config.dry_run() {
             return;
         }
-        self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
+        self.verbose_than(1, || eprintln!("Copy/Link {src:?} to {dst:?}"));
         if src == dst {
             return;
         }
@@ -1802,7 +1775,7 @@ Executed at: {executed_at}"#,
             return;
         }
         let dst = dstdir.join(src.file_name().unwrap());
-        self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
+        self.verbose_than(1, || eprintln!("Install {src:?} to {dst:?}"));
         t!(fs::create_dir_all(dstdir));
         if !src.exists() {
             panic!("ERROR: File \"{}\" not found!", src.display());
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 0df00469452..e8d5b60948a 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -155,15 +155,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
         build.cxx.borrow_mut().insert(target, compiler);
     }
 
-    build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
-    build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
+    build.verbose(|| eprintln!("CC_{} = {:?}", target.triple, build.cc(target)));
+    build.verbose(|| eprintln!("CFLAGS_{} = {cflags:?}", target.triple));
     if let Ok(cxx) = build.cxx(target) {
         let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
-        build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
-        build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
+        build.verbose(|| eprintln!("CXX_{} = {cxx:?}", target.triple));
+        build.verbose(|| eprintln!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
     }
     if let Some(ar) = ar {
-        build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
+        build.verbose(|| eprintln!("AR_{} = {ar:?}", target.triple));
         build.ar.borrow_mut().insert(target, ar);
     }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 41a541d7269..f4f189c718a 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -310,4 +310,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "Revert `rust.download-rustc` global default to `false` and only use `rust.download-rustc = \"if-unchanged\"` default for library and tools profile. As alt CI rustc is built without debug assertions, `rust.debug-assertions = true` will now inhibit downloading CI rustc.",
     },
+    ChangeInfo {
+        change_id: 133853,
+        severity: ChangeSeverity::Info,
+        summary: "`build.vendor` is now enabled by default for dist/tarball sources when 'vendor' directory and '.cargo/config.toml' file are present.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 079213e8c3d..c0d52fd3430 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -55,7 +55,7 @@ pub fn exe(name: &str, target: TargetSelection) -> String {
 
 /// Returns `true` if the file name given looks like a dynamic library.
 pub fn is_dylib(path: &Path) -> bool {
-    path.extension().and_then(|ext| ext.to_str()).map_or(false, |ext| {
+    path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| {
         ext == "dylib" || ext == "so" || ext == "dll" || (ext == "a" && is_aix_shared_archive(path))
     })
 }
@@ -135,7 +135,7 @@ impl Drop for TimeIt {
     fn drop(&mut self) {
         let time = self.1.elapsed();
         if !self.0 {
-            println!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
+            eprintln!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
         }
     }
 }
@@ -267,12 +267,12 @@ pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
     let status = match cmd.as_command_mut().status() {
         Ok(status) => status,
         Err(e) => {
-            println!("failed to execute command: {cmd:?}\nERROR: {e}");
+            eprintln!("failed to execute command: {cmd:?}\nERROR: {e}");
             return false;
         }
     };
     if !status.success() && print_cmd_on_fail {
-        println!(
+        eprintln!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {status}\n\n"
         );
diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs
index c5e892450c4..fb69d331d27 100644
--- a/src/bootstrap/src/utils/job.rs
+++ b/src/bootstrap/src/utils/job.rs
@@ -15,11 +15,12 @@ pub unsafe fn setup(build: &mut crate::Build) {
 ///
 /// Most of the time when you're running a build system (e.g., make) you expect
 /// Ctrl-C or abnormal termination to actually terminate the entire tree of
-/// process in play, not just the one at the top. This currently works "by
+/// processes in play. This currently works "by
 /// default" on Unix platforms because Ctrl-C actually sends a signal to the
-/// *process group* rather than the parent process, so everything will get torn
-/// down. On Windows, however, this does not happen and Ctrl-C just kills the
-/// parent process.
+/// *process group* so everything will get torn
+/// down. On Windows, however, Ctrl-C is only sent to processes in the same console.
+/// If a process is detached or attached to another console, it won't receive the
+/// signal.
 ///
 /// To achieve the same semantics on Windows we use Job Objects to ensure that
 /// all processes die at the same time. Job objects have a mode of operation
@@ -87,15 +88,7 @@ mod for_windows {
         );
         assert!(r.is_ok(), "{}", io::Error::last_os_error());
 
-        // Assign our process to this job object. Note that if this fails, one very
-        // likely reason is that we are ourselves already in a job object! This can
-        // happen on the build bots that we've got for Windows, or if just anyone
-        // else is instrumenting the build. In this case we just bail out
-        // immediately and assume that they take care of it.
-        //
-        // Also note that nested jobs (why this might fail) are supported in recent
-        // versions of Windows, but the version of Windows that our bots are running
-        // at least don't support nested job objects.
+        // Assign our process to this job object.
         let r = AssignProcessToJobObject(job, GetCurrentProcess());
         if r.is_err() {
             CloseHandle(job).ok();
@@ -124,14 +117,19 @@ mod for_windows {
                 // (only when wrongly setting the environmental variable),
                 // it might be better to improve the experience of the second case
                 // when users have interrupted the parent process and we haven't finish
-                // duplicating the handle yet. We just need close the job object if that occurs.
-                CloseHandle(job).ok();
+                // duplicating the handle yet.
                 return;
             }
         };
 
         let mut parent_handle = HANDLE::default();
-        let r = DuplicateHandle(
+        // If this fails, well at least we tried! An example of DuplicateHandle
+        // failing in the past has been when the wrong python2 package spawned this
+        // build system (e.g., the `python2` package in MSYS instead of
+        // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
+        // mode" here is that we only clean everything up when the build system
+        // dies, not when the python parent does, so not too bad.
+        let _ = DuplicateHandle(
             GetCurrentProcess(),
             job,
             parent,
@@ -140,15 +138,6 @@ mod for_windows {
             false,
             DUPLICATE_SAME_ACCESS,
         );
-
-        // If this failed, well at least we tried! An example of DuplicateHandle
-        // failing in the past has been when the wrong python2 package spawned this
-        // build system (e.g., the `python2` package in MSYS instead of
-        // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
-        // mode" here is that we only clean everything up when the build system
-        // dies, not when the python parent does, so not too bad.
-        if r.is_err() {
-            CloseHandle(job).ok();
-        }
+        CloseHandle(parent).ok();
     }
 }
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 3b31fa36e88..06d3add6281 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -56,7 +56,7 @@ impl BuildMetrics {
             running_steps: Vec::new(),
 
             system_info: System::new_with_specifics(
-                RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
+                RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
             ),
             timer_start: None,
             invocation_timer_start: Instant::now(),
@@ -161,8 +161,9 @@ impl BuildMetrics {
 
         let dest = build.out.join("metrics.json");
 
-        let mut system =
-            System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything()));
+        let mut system = System::new_with_specifics(
+            RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
+        );
         system.refresh_cpu_usage();
         system.refresh_memory();
 
@@ -184,7 +185,7 @@ impl BuildMetrics {
                 if version.format_version == CURRENT_FORMAT_VERSION {
                     t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
                 } else {
-                    println!(
+                    eprintln!(
                         "WARNING: overriding existing build/metrics.json, as it's not \
                          compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
                     );
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index eb2c8254dc0..7a3ec61c6da 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -56,7 +56,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
     let cmd = cmd.as_command_mut();
     cmd.stdout(Stdio::piped());
 
-    builder.verbose(|| println!("running: {cmd:?}"));
+    builder.verbose(|| eprintln!("running: {cmd:?}"));
 
     let mut process = cmd.spawn().unwrap();
 
@@ -71,7 +71,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
 
     let result = process.wait_with_output().unwrap();
     if !result.status.success() && builder.is_verbose() {
-        println!(
+        eprintln!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {}",
             result.status
@@ -135,7 +135,9 @@ impl<'a> Renderer<'a> {
         if self.up_to_date_tests > 0 {
             let n = self.up_to_date_tests;
             let s = if n > 1 { "s" } else { "" };
-            println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
+            eprintln!(
+                "help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"
+            );
         }
     }
 
@@ -185,12 +187,12 @@ impl<'a> Renderer<'a> {
     }
 
     fn render_test_outcome_verbose(&self, outcome: Outcome<'_>, test: &TestOutcome) {
-        print!("test {} ... ", test.name);
-        self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
+        eprint!("test {} ... ", test.name);
+        self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
         if let Some(exec_time) = test.exec_time {
-            print!(" ({exec_time:.2?})");
+            eprint!(" ({exec_time:.2?})");
         }
-        println!();
+        eprintln!();
     }
 
     fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
@@ -198,45 +200,45 @@ impl<'a> Renderer<'a> {
             if let Some(total) = self.tests_count {
                 let total = total.to_string();
                 let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len());
-                print!(" {executed}/{total}");
+                eprint!(" {executed}/{total}");
             }
-            println!();
+            eprintln!();
             self.terse_tests_in_line = 0;
         }
 
         self.terse_tests_in_line += 1;
-        self.builder.colored_stdout(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
+        self.builder.colored_stderr(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
         let _ = std::io::stdout().flush();
     }
 
     fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
         // The terse output doesn't end with a newline, so we need to add it ourselves.
         if !self.builder.config.verbose_tests {
-            println!();
+            eprintln!();
         }
 
         if !self.failures.is_empty() {
-            println!("\nfailures:\n");
+            eprintln!("\nfailures:\n");
             for failure in &self.failures {
                 if failure.stdout.is_some() || failure.message.is_some() {
-                    println!("---- {} stdout ----", failure.name);
+                    eprintln!("---- {} stdout ----", failure.name);
                     if let Some(stdout) = &failure.stdout {
-                        println!("{stdout}");
+                        eprintln!("{stdout}");
                     }
                     if let Some(message) = &failure.message {
-                        println!("NOTE: {message}");
+                        eprintln!("NOTE: {message}");
                     }
                 }
             }
 
-            println!("\nfailures:");
+            eprintln!("\nfailures:");
             for failure in &self.failures {
-                println!("    {}", failure.name);
+                eprintln!("    {}", failure.name);
             }
         }
 
         if !self.benches.is_empty() {
-            println!("\nbenchmarks:");
+            eprintln!("\nbenchmarks:");
 
             let mut rows = Vec::new();
             for bench in &self.benches {
@@ -251,13 +253,13 @@ impl<'a> Renderer<'a> {
             let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0);
             let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0);
             for row in &rows {
-                println!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
+                eprintln!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
             }
         }
 
-        print!("\ntest result: ");
-        self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
-        println!(
+        eprint!("\ntest result: ");
+        self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
+        eprintln!(
             ". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n",
             suite.passed,
             suite.failed,
@@ -274,7 +276,7 @@ impl<'a> Renderer<'a> {
     fn render_message(&mut self, message: Message) {
         match message {
             Message::Suite(SuiteMessage::Started { test_count }) => {
-                println!("\nrunning {test_count} tests");
+                eprintln!("\nrunning {test_count} tests");
                 self.executed_tests = 0;
                 self.terse_tests_in_line = 0;
                 self.tests_count = Some(test_count);
@@ -314,7 +316,7 @@ impl<'a> Renderer<'a> {
                 self.failures.push(outcome);
             }
             Message::Test(TestMessage::Timeout { name }) => {
-                println!("test {name} has been running for a long time");
+                eprintln!("test {name} has been running for a long time");
             }
             Message::Test(TestMessage::Started) => {} // Not useful
         }
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 3c6c7a7fa18..f60498a4872 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -344,7 +344,7 @@ impl<'a> Tarball<'a> {
         // For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
         let compression_profile = if self.builder.kind == Kind::Install {
             self.builder.verbose(|| {
-                println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
+                eprintln!("Forcing dist.compression-profile = 'no-op' for `x install`.")
             });
             // "no-op" indicates that the rust-installer won't produce compressed tarball sources.
             "no-op"
diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py
index adfd895ead0..3d9dc86734f 100755
--- a/src/ci/cpu-usage-over-time.py
+++ b/src/ci/cpu-usage-over-time.py
@@ -40,12 +40,13 @@ import time
 # Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just
 # "linux". We check here with `.startswith` to keep compatibility with older
 # Python versions (especially Python 2.7).
-if sys.platform.startswith('linux'):
+if sys.platform.startswith("linux"):
+
     class State:
         def __init__(self):
-            with open('/proc/stat', 'r') as file:
+            with open("/proc/stat", "r") as file:
                 data = file.readline().split()
-            if data[0] != 'cpu':
+            if data[0] != "cpu":
                 raise Exception('did not start with "cpu"')
             self.user = int(data[1])
             self.nice = int(data[2])
@@ -69,10 +70,21 @@ if sys.platform.startswith('linux'):
             steal = self.steal - prev.steal
             guest = self.guest - prev.guest
             guest_nice = self.guest_nice - prev.guest_nice
-            total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice
+            total = (
+                user
+                + nice
+                + system
+                + idle
+                + iowait
+                + irq
+                + softirq
+                + steal
+                + guest
+                + guest_nice
+            )
             return float(idle) / float(total) * 100
 
-elif sys.platform == 'win32':
+elif sys.platform == "win32":
     from ctypes.wintypes import DWORD
     from ctypes import Structure, windll, WinError, GetLastError, byref
 
@@ -104,9 +116,10 @@ elif sys.platform == 'win32':
             kernel = self.kernel - prev.kernel
             return float(idle) / float(user + kernel) * 100
 
-elif sys.platform == 'darwin':
+elif sys.platform == "darwin":
     from ctypes import *
-    libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
+
+    libc = cdll.LoadLibrary("/usr/lib/libc.dylib")
 
     class host_cpu_load_info_data_t(Structure):
         _fields_ = [("cpu_ticks", c_uint * 4)]
@@ -116,7 +129,7 @@ elif sys.platform == 'darwin':
         c_uint,
         c_int,
         POINTER(host_cpu_load_info_data_t),
-        POINTER(c_int)
+        POINTER(c_int),
     ]
     host_statistics.restype = c_int
 
@@ -124,13 +137,14 @@ elif sys.platform == 'darwin':
     CPU_STATE_SYSTEM = 1
     CPU_STATE_IDLE = 2
     CPU_STATE_NICE = 3
+
     class State:
         def __init__(self):
             stats = host_cpu_load_info_data_t()
-            count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT
+            count = c_int(4)  # HOST_CPU_LOAD_INFO_COUNT
             err = libc.host_statistics(
                 libc.mach_host_self(),
-                c_int(3), # HOST_CPU_LOAD_INFO
+                c_int(3),  # HOST_CPU_LOAD_INFO
                 byref(stats),
                 byref(count),
             )
@@ -148,7 +162,7 @@ elif sys.platform == 'darwin':
             return float(idle) / float(user + system + idle + nice) * 100.0
 
 else:
-    print('unknown platform', sys.platform)
+    print("unknown platform", sys.platform)
     sys.exit(1)
 
 cur_state = State()
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-arm-linux/Dockerfile
index 420c42bc9d8..4a749473004 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-aarch64/dist-arm-linux/Dockerfile
@@ -19,7 +19,7 @@ RUN sh /scripts/rustbuild-setup.sh
 WORKDIR /tmp
 
 COPY scripts/crosstool-ng-build.sh /scripts/
-COPY host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig /tmp/crosstool.defconfig
+COPY host-aarch64/dist-arm-linux/arm-linux-gnueabi.defconfig /tmp/crosstool.defconfig
 RUN /scripts/crosstool-ng-build.sh
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig b/src/ci/docker/host-aarch64/dist-arm-linux/arm-linux-gnueabi.defconfig
index e7afdbe9d4d..e7afdbe9d4d 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig
+++ b/src/ci/docker/host-aarch64/dist-arm-linux/arm-linux-gnueabi.defconfig
diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile
index 222fa8a7355..aade9588268 100644
--- a/src/ci/docker/host-x86_64/arm-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:23.04
+FROM ubuntu:24.04
 
 ARG DEBIAN_FRONTEND=noninteractive
 COPY scripts/android-base-apt-get.sh /scripts/
@@ -11,7 +11,8 @@ RUN . /scripts/android-ndk.sh && \
 RUN dpkg --add-architecture i386 && \
     apt-get update && \
     apt-get install -y --no-install-recommends \
-  libgl1-mesa-glx \
+  libgl1 \
+  libglx-mesa0 \
   libpulse0 \
   libstdc++6:i386 \
   openjdk-8-jre-headless \
diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile
index 54649e0d22b..95fed6ee767 100644
--- a/src/ci/docker/host-x86_64/dist-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:23.04
+FROM ubuntu:24.04
 
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
diff --git a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile
index 6dff3095b46..bbbf0b3adf2 100644
--- a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:23.04
+FROM ubuntu:24.04
 
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index e2b66c2cff1..e2736720607 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -27,5 +27,5 @@ RUN echo "[rust]" > /config/nopt-std-config.toml
 RUN echo "optimize = false" >> /config/nopt-std-config.toml
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
-ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
-  && python3 ../x.py --stage 2 test
+ARG SCRIPT_ARG
+ENV SCRIPT=${SCRIPT_ARG}
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index 61811c41904..dec25461bb4 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -24,10 +24,5 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
-# Skip some tests that are unlikely to be platform specific, to speed up
-# this slow job.
-ENV SCRIPT python3 ../x.py --stage 2 test \
-  --skip src/bootstrap \
-  --skip tests/rustdoc-js \
-  --skip src/tools/error_index_generator \
-  --skip src/tools/linkchecker
+ARG SCRIPT_ARG
+ENV SCRIPT=${SCRIPT_ARG}
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py
index 3577643ca55..4f877389fbc 100755
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py
+++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py
@@ -8,78 +8,79 @@ import tempfile
 
 from pathlib import Path
 
-TARGET_AARCH64 = 'aarch64-unknown-uefi'
-TARGET_I686 = 'i686-unknown-uefi'
-TARGET_X86_64 = 'x86_64-unknown-uefi'
+TARGET_AARCH64 = "aarch64-unknown-uefi"
+TARGET_I686 = "i686-unknown-uefi"
+TARGET_X86_64 = "x86_64-unknown-uefi"
+
 
 def run(*cmd, capture=False, check=True, env=None, timeout=None):
     """Print and run a command, optionally capturing the output."""
     cmd = [str(p) for p in cmd]
-    print(' '.join(cmd))
-    return subprocess.run(cmd,
-                          capture_output=capture,
-                          check=check,
-                          env=env,
-                          text=True,
-                          timeout=timeout)
+    print(" ".join(cmd))
+    return subprocess.run(
+        cmd, capture_output=capture, check=check, env=env, text=True, timeout=timeout
+    )
+
 
 def build_and_run(tmp_dir, target):
     if target == TARGET_AARCH64:
-        boot_file_name = 'bootaa64.efi'
-        ovmf_dir = Path('/usr/share/AAVMF')
-        ovmf_code = 'AAVMF_CODE.fd'
-        ovmf_vars = 'AAVMF_VARS.fd'
-        qemu = 'qemu-system-aarch64'
-        machine = 'virt'
-        cpu = 'cortex-a72'
+        boot_file_name = "bootaa64.efi"
+        ovmf_dir = Path("/usr/share/AAVMF")
+        ovmf_code = "AAVMF_CODE.fd"
+        ovmf_vars = "AAVMF_VARS.fd"
+        qemu = "qemu-system-aarch64"
+        machine = "virt"
+        cpu = "cortex-a72"
     elif target == TARGET_I686:
-        boot_file_name = 'bootia32.efi'
-        ovmf_dir = Path('/usr/share/OVMF')
-        ovmf_code = 'OVMF32_CODE_4M.secboot.fd'
-        ovmf_vars = 'OVMF32_VARS_4M.fd'
+        boot_file_name = "bootia32.efi"
+        ovmf_dir = Path("/usr/share/OVMF")
+        ovmf_code = "OVMF32_CODE_4M.secboot.fd"
+        ovmf_vars = "OVMF32_VARS_4M.fd"
         # The i686 target intentionally uses 64-bit qemu; the important
         # difference is that the OVMF code provides a 32-bit environment.
-        qemu = 'qemu-system-x86_64'
-        machine = 'q35'
-        cpu = 'qemu64'
+        qemu = "qemu-system-x86_64"
+        machine = "q35"
+        cpu = "qemu64"
     elif target == TARGET_X86_64:
-        boot_file_name = 'bootx64.efi'
-        ovmf_dir = Path('/usr/share/OVMF')
-        ovmf_code = 'OVMF_CODE.fd'
-        ovmf_vars = 'OVMF_VARS.fd'
-        qemu = 'qemu-system-x86_64'
-        machine = 'q35'
-        cpu = 'qemu64'
+        boot_file_name = "bootx64.efi"
+        ovmf_dir = Path("/usr/share/OVMF")
+        ovmf_code = "OVMF_CODE.fd"
+        ovmf_vars = "OVMF_VARS.fd"
+        qemu = "qemu-system-x86_64"
+        machine = "q35"
+        cpu = "qemu64"
     else:
-        raise KeyError('invalid target')
+        raise KeyError("invalid target")
 
-    host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu')
-    stage0 = host_artifacts / 'stage0/bin'
-    stage2 = host_artifacts / 'stage2/bin'
+    host_artifacts = Path("/checkout/obj/build/x86_64-unknown-linux-gnu")
+    stage0 = host_artifacts / "stage0/bin"
+    stage2 = host_artifacts / "stage2/bin"
 
     env = dict(os.environ)
-    env['PATH'] = '{}:{}:{}'.format(stage2, stage0, env['PATH'])
+    env["PATH"] = "{}:{}:{}".format(stage2, stage0, env["PATH"])
 
     # Copy the test create into `tmp_dir`.
-    test_crate = Path(tmp_dir) / 'uefi_qemu_test'
-    shutil.copytree('/uefi_qemu_test', test_crate)
+    test_crate = Path(tmp_dir) / "uefi_qemu_test"
+    shutil.copytree("/uefi_qemu_test", test_crate)
 
     # Build the UEFI executable.
-    run('cargo',
-        'build',
-        '--manifest-path',
-        test_crate / 'Cargo.toml',
-        '--target',
+    run(
+        "cargo",
+        "build",
+        "--manifest-path",
+        test_crate / "Cargo.toml",
+        "--target",
         target,
-        env=env)
+        env=env,
+    )
 
     # Create a mock EFI System Partition in a subdirectory.
-    esp = test_crate / 'esp'
-    boot = esp / 'efi/boot'
+    esp = test_crate / "esp"
+    boot = esp / "efi/boot"
     os.makedirs(boot, exist_ok=True)
 
     # Copy the executable into the ESP.
-    src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi'
+    src_exe_path = test_crate / "target" / target / "debug/uefi_qemu_test.efi"
     shutil.copy(src_exe_path, boot / boot_file_name)
     print(src_exe_path, boot / boot_file_name)
 
@@ -89,37 +90,39 @@ def build_and_run(tmp_dir, target):
 
     # Make a writable copy of the vars file. aarch64 doesn't boot
     # correctly with read-only vars.
-    ovmf_rw_vars = Path(tmp_dir) / 'vars.fd'
+    ovmf_rw_vars = Path(tmp_dir) / "vars.fd"
     shutil.copy(ovmf_vars, ovmf_rw_vars)
 
     # Run the executable in QEMU and capture the output.
-    output = run(qemu,
-                 '-machine',
-                 machine,
-                 '-cpu',
-                 cpu,
-                 '-display',
-                 'none',
-                 '-serial',
-                 'stdio',
-                 '-drive',
-                 f'if=pflash,format=raw,readonly=on,file={ovmf_code}',
-                 '-drive',
-                 f'if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}',
-                 '-drive',
-                 f'format=raw,file=fat:rw:{esp}',
-                 capture=True,
-                 check=True,
-                 # Set a timeout to kill the VM in case something goes wrong.
-                 timeout=60).stdout
-
-    if 'Hello World!' in output:
-        print('VM produced expected output')
+    output = run(
+        qemu,
+        "-machine",
+        machine,
+        "-cpu",
+        cpu,
+        "-display",
+        "none",
+        "-serial",
+        "stdio",
+        "-drive",
+        f"if=pflash,format=raw,readonly=on,file={ovmf_code}",
+        "-drive",
+        f"if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}",
+        "-drive",
+        f"format=raw,file=fat:rw:{esp}",
+        capture=True,
+        check=True,
+        # Set a timeout to kill the VM in case something goes wrong.
+        timeout=60,
+    ).stdout
+
+    if "Hello World!" in output:
+        print("VM produced expected output")
     else:
-        print('unexpected VM output:')
-        print('---start---')
+        print("unexpected VM output:")
+        print("---start---")
         print(output)
-        print('---end---')
+        print("---end---")
         sys.exit(1)
 
 
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 6b2d58c8ef3..7211b157c69 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.18.1
\ No newline at end of file
+0.18.2
\ No newline at end of file
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index d554186df4c..a0adf60b6b2 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -105,6 +105,23 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
     # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
     CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
 
+    # Docker build arguments.
+    build_args=(
+        "build"
+        "--rm"
+        "-t" "rust-ci"
+        "-f" "$dockerfile"
+        "$context"
+    )
+
+    # If the environment variable DOCKER_SCRIPT is defined,
+    # set the build argument SCRIPT_ARG to DOCKER_SCRIPT.
+    # In this way, we run the script defined in CI,
+    # instead of the one defined in the Dockerfile.
+    if [ -n "${DOCKER_SCRIPT+x}" ]; then
+      build_args+=("--build-arg" "SCRIPT_ARG=${DOCKER_SCRIPT}")
+    fi
+
     # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci
     # ghcr.io registry. If it is not possible, we fall back to building the image
     # locally.
@@ -115,7 +132,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
             docker tag "${IMAGE_TAG}" rust-ci
         else
             echo "Building local Docker image"
-            retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+            retry docker "${build_args[@]}"
         fi
     # On PR CI jobs, we don't have permissions to write to the registry cache,
     # but we can still read from it.
@@ -127,13 +144,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
         # Build the image using registry caching backend
         retry docker \
           buildx \
-          build \
-          --rm \
-          -t rust-ci \
-          -f "$dockerfile" \
+          "${build_args[@]}" \
           --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
-          --output=type=docker \
-          "$context"
+          --output=type=docker
     # On auto/try builds, we can also write to the cache.
     else
         # Log into the Docker registry, so that we can read/write cache and the final image
@@ -147,14 +160,10 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
         # Build the image using registry caching backend
         retry docker \
           buildx \
-          build \
-          --rm \
-          -t rust-ci \
-          -f "$dockerfile" \
+          "${build_args[@]}" \
           --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
           --cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \
-          --output=type=docker \
-          "$context"
+          --output=type=docker
 
         # Print images for debugging purposes
         docker images
diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh
index 22e2e243e43..d0252e356fd 100644
--- a/src/ci/docker/scripts/android-base-apt-get.sh
+++ b/src/ci/docker/scripts/android-base-apt-get.sh
@@ -10,7 +10,7 @@ apt-get install -y --no-install-recommends \
   g++ \
   git \
   libssl-dev \
-  libncurses5 \
+  libncurses-dev \
   make \
   ninja-build \
   pkg-config \
diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py
index 66cba58427b..6356f15a886 100755
--- a/src/ci/docker/scripts/android-sdk-manager.py
+++ b/src/ci/docker/scripts/android-sdk-manager.py
@@ -35,6 +35,7 @@ MIRROR_BUCKET = "rust-lang-ci-mirrors"
 MIRROR_BUCKET_REGION = "us-west-1"
 MIRROR_BASE_DIR = "rustc/android/"
 
+
 class Package:
     def __init__(self, path, url, sha1, deps=None):
         if deps is None:
@@ -53,18 +54,25 @@ class Package:
             sha1 = hashlib.sha1(f.read()).hexdigest()
             if sha1 != self.sha1:
                 raise RuntimeError(
-                    "hash mismatch for package " + self.path + ": " +
-                    sha1 + " vs " + self.sha1 + " (known good)"
+                    "hash mismatch for package "
+                    + self.path
+                    + ": "
+                    + sha1
+                    + " vs "
+                    + self.sha1
+                    + " (known good)"
                 )
         return file
 
     def __repr__(self):
-        return "<Package "+self.path+" at "+self.url+" (sha1="+self.sha1+")"
+        return "<Package " + self.path + " at " + self.url + " (sha1=" + self.sha1 + ")"
+
 
 def fetch_url(url):
     page = urllib.request.urlopen(url)
     return page.read()
 
+
 def fetch_repository(base, repo_url):
     packages = {}
     root = ET.fromstring(fetch_url(base + repo_url))
@@ -92,12 +100,14 @@ def fetch_repository(base, repo_url):
 
     return packages
 
+
 def fetch_repositories():
     packages = {}
     for repo in REPOSITORIES:
         packages.update(fetch_repository(BASE_REPOSITORY, repo))
     return packages
 
+
 class Lockfile:
     def __init__(self, path):
         self.path = path
@@ -123,6 +133,7 @@ class Lockfile:
             for package in packages:
                 f.write(package.path + " " + package.url + " " + package.sha1 + "\n")
 
+
 def cli_add_to_lockfile(args):
     lockfile = Lockfile(args.lockfile)
     packages = fetch_repositories()
@@ -130,28 +141,49 @@ def cli_add_to_lockfile(args):
         lockfile.add(packages, package)
     lockfile.save()
 
+
 def cli_update_mirror(args):
     lockfile = Lockfile(args.lockfile)
     for package in lockfile.packages.values():
         path = package.download(BASE_REPOSITORY)
-        subprocess.run([
-            "aws", "s3", "mv", path,
-            "s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url,
-            "--profile=" + args.awscli_profile,
-        ], check=True)
+        subprocess.run(
+            [
+                "aws",
+                "s3",
+                "mv",
+                path,
+                "s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url,
+                "--profile=" + args.awscli_profile,
+            ],
+            check=True,
+        )
+
 
 def cli_install(args):
     lockfile = Lockfile(args.lockfile)
     for package in lockfile.packages.values():
         # Download the file from the mirror into a temp file
-        url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \
-              ".amazonaws.com/" + MIRROR_BASE_DIR
+        url = (
+            "https://"
+            + MIRROR_BUCKET
+            + ".s3-"
+            + MIRROR_BUCKET_REGION
+            + ".amazonaws.com/"
+            + MIRROR_BASE_DIR
+        )
         downloaded = package.download(url)
         # Extract the file in a temporary directory
         extract_dir = tempfile.mkdtemp()
-        subprocess.run([
-            "unzip", "-q", downloaded, "-d", extract_dir,
-        ], check=True)
+        subprocess.run(
+            [
+                "unzip",
+                "-q",
+                downloaded,
+                "-d",
+                extract_dir,
+            ],
+            check=True,
+        )
         # Figure out the prefix used in the zip
         subdirs = [d for d in os.listdir(extract_dir) if not d.startswith(".")]
         if len(subdirs) != 1:
@@ -162,6 +194,7 @@ def cli_install(args):
         os.rename(os.path.join(extract_dir, subdirs[0]), dest)
         os.unlink(downloaded)
 
+
 def cli():
     parser = argparse.ArgumentParser()
     subparsers = parser.add_subparsers()
@@ -187,5 +220,6 @@ def cli():
         exit(1)
     args.func(args)
 
+
 if __name__ == "__main__":
     cli()
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 77e2741f9ea..4a30de5a263 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -588,7 +588,7 @@ class TestEnvironment:
                 "--repo-path",
                 self.repo_dir(),
                 "--repository",
-                self.TEST_REPO_NAME
+                self.TEST_REPO_NAME,
             ],
             env=ffx_env,
             stdout_handler=self.subprocess_logger.debug,
@@ -619,9 +619,7 @@ class TestEnvironment:
     # `facet` statement required for TCP testing via
     # protocol `fuchsia.posix.socket.Provider`. See
     # https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#legacy_non-hermetic_tests
-    CML_TEMPLATE: ClassVar[
-        str
-    ] = """
+    CML_TEMPLATE: ClassVar[str] = """
     {{
         program: {{
             runner: "elf_test_runner",
@@ -994,7 +992,7 @@ class TestEnvironment:
                 "repository",
                 "server",
                 "stop",
-                self.TEST_REPO_NAME
+                self.TEST_REPO_NAME,
             ],
             env=self.ffx_cmd_env(),
             stdout_handler=self.subprocess_logger.debug,
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index f07515f7784..8776e0f0be9 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,7 @@
 
 set -euo pipefail
 
-LINUX_VERSION=28e848386b92645f93b9f2fdba5882c3ca7fb3e2
+LINUX_VERSION=v6.13-rc1
 
 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt
 ../x.py build --stage 2 library rustdoc clippy rustfmt
@@ -64,7 +64,7 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \
 
 BUILD_TARGETS="
     samples/rust/rust_minimal.o
-    samples/rust/rust_print.o
+    samples/rust/rust_print_main.o
     drivers/net/phy/ax88796b_rust.o
     rust/doctests_kernel_generated.o
 "
diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py
index 7de6d5fcd5f..1f994f0ffd2 100755
--- a/src/ci/github-actions/calculate-job-matrix.py
+++ b/src/ci/github-actions/calculate-job-matrix.py
@@ -7,6 +7,7 @@ be executed on CI.
 It reads job definitions from `src/ci/github-actions/jobs.yml`
 and filters them based on the event that happened on CI.
 """
+
 import dataclasses
 import json
 import logging
@@ -94,7 +95,7 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
         try_build = ctx.ref in (
             "refs/heads/try",
             "refs/heads/try-perf",
-            "refs/heads/automation/bors/try"
+            "refs/heads/automation/bors/try",
         )
 
         # Unrolled branch from a rollup for testing perf
@@ -135,11 +136,15 @@ def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[
                     continue
                 jobs.append(job[0])
             if unknown_jobs:
-                raise Exception(f"Custom job(s) `{unknown_jobs}` not found in auto jobs")
+                raise Exception(
+                    f"Custom job(s) `{unknown_jobs}` not found in auto jobs"
+                )
 
         return add_base_env(name_jobs(jobs, "try"), job_data["envs"]["try"])
     elif isinstance(run_type, AutoRunType):
-        return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"])
+        return add_base_env(
+            name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]
+        )
 
     return []
 
@@ -161,7 +166,7 @@ def get_github_ctx() -> GitHubCtx:
         event_name=event_name,
         ref=os.environ["GITHUB_REF"],
         repository=os.environ["GITHUB_REPOSITORY"],
-        commit_message=commit_message
+        commit_message=commit_message,
     )
 
 
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 2f59892acf6..959a9580e60 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -43,7 +43,7 @@ runners:
     os: windows-2022-16core-64gb
     <<: *base-job
 
-  - &job-aarch64-linux
+  - &job-linux-8c-aarch64
     os: ubuntu-22.04-arm64-8core-32gb
 
 envs:
@@ -58,6 +58,22 @@ envs:
     NO_DEBUG_ASSERTIONS: 1
     NO_OVERFLOW_CHECKS: 1
 
+  # Different set of tests to run tests in parallel in multiple jobs.
+  stage_2_test_set1: &stage_2_test_set1
+    DOCKER_SCRIPT: >-
+      python3 ../x.py --stage 2 test
+      --skip compiler
+      --skip src
+
+  stage_2_test_set2: &stage_2_test_set2
+    DOCKER_SCRIPT: >-
+      python3 ../x.py --stage 2 test
+      --skip tests
+      --skip coverage-map
+      --skip coverage-run
+      --skip library
+      --skip tidyselftest
+
   production:
     &production
     DEPLOY_BUCKET: rust-lang-ci2
@@ -123,10 +139,10 @@ auto:
   #############################
 
   - image: aarch64-gnu
-    <<: *job-aarch64-linux
+    <<: *job-linux-8c-aarch64
 
   - image: aarch64-gnu-debug
-    <<: *job-aarch64-linux
+    <<: *job-linux-8c-aarch64
 
   - image: arm-android
     <<: *job-linux-4c
@@ -143,7 +159,7 @@ auto:
     <<: *job-linux-4c
 
   - image: dist-arm-linux
-    <<: *job-linux-8c
+    <<: *job-linux-8c-aarch64
 
   - image: dist-armhf-linux
     <<: *job-linux-4c
@@ -212,11 +228,42 @@ auto:
   - image: dist-x86_64-netbsd
     <<: *job-linux-4c
 
-  - image: i686-gnu
-    <<: *job-linux-8c
+  # The i686-gnu job is split into multiple jobs to run tests in parallel.
+  # i686-gnu-1 skips tests that run in i686-gnu-2.
+  - image: i686-gnu-1
+    env:
+      IMAGE: i686-gnu
+      <<: *stage_2_test_set1
+    <<: *job-linux-4c
 
-  - image: i686-gnu-nopt
-    <<: *job-linux-8c
+  # Skip tests that run in i686-gnu-1
+  - image: i686-gnu-2
+    env:
+      IMAGE: i686-gnu
+      <<: *stage_2_test_set2
+    <<: *job-linux-4c
+
+  # The i686-gnu-nopt job is split into multiple jobs to run tests in parallel.
+  # i686-gnu-nopt-1 skips tests that run in i686-gnu-nopt-2
+  - image: i686-gnu-nopt-1
+    env:
+      IMAGE: i686-gnu-nopt
+      <<: *stage_2_test_set1
+    <<: *job-linux-4c
+
+  # Skip tests that run in i686-gnu-nopt-1
+  - image: i686-gnu-nopt-2
+    env:
+      IMAGE: i686-gnu-nopt
+      DOCKER_SCRIPT: >-
+        python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std &&
+        python3 ../x.py --stage 2 test
+        --skip tests
+        --skip coverage-map
+        --skip coverage-run
+        --skip library
+        --skip tidyselftest
+    <<: *job-linux-4c
 
   - image: mingw-check
     <<: *job-linux-4c
@@ -338,6 +385,7 @@ auto:
         --set rust.jemalloc
         --set llvm.ninja=false
         --set rust.lto=thin
+        --set rust.codegen-units=1
       RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       SELECT_XCODE: /Applications/Xcode_15.4.app
       USE_XCODE_CLANG: 1
@@ -439,14 +487,24 @@ auto:
       NO_DOWNLOAD_CI_LLVM: 1
     <<: *job-windows-8c
 
-  - image: x86_64-mingw
+  # x86_64-mingw is split into two jobs to run tests in parallel.
+  - image: x86_64-mingw-1
     env:
-      SCRIPT: make ci-mingw
+      SCRIPT: make ci-mingw-x
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
-    <<: *job-windows-8c
+    <<: *job-windows
+
+  - image: x86_64-mingw-2
+    env:
+      SCRIPT: make ci-mingw-bootstrap
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+    <<: *job-windows
 
   - image: dist-x86_64-msvc
     env:
diff --git a/src/ci/scripts/upload-build-metrics.py b/src/ci/scripts/upload-build-metrics.py
index a95e0949d70..23061884a39 100644
--- a/src/ci/scripts/upload-build-metrics.py
+++ b/src/ci/scripts/upload-build-metrics.py
@@ -19,6 +19,7 @@ $ python3 upload-build-metrics.py <path-to-CPU-usage-CSV>
 
 `path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script.
 """
+
 import argparse
 import csv
 import os
@@ -31,7 +32,7 @@ from typing import List
 def load_cpu_usage(path: Path) -> List[float]:
     usage = []
     with open(path) as f:
-        reader = csv.reader(f, delimiter=',')
+        reader = csv.reader(f, delimiter=",")
         for row in reader:
             # The log might contain incomplete rows or some Python exception
             if len(row) == 2:
@@ -50,25 +51,21 @@ def upload_datadog_measure(name: str, value: float):
     print(f"Metric {name}: {value:.4f}")
 
     datadog_cmd = "datadog-ci"
-    if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith("win"):
+    if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith(
+        "win"
+    ):
         # Due to weird interaction of MSYS2 and Python, we need to use an absolute path,
         # and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771.
         datadog_cmd = "C:\\npm\\prefix\\datadog-ci.cmd"
 
-    subprocess.run([
-        datadog_cmd,
-        "measure",
-        "--level", "job",
-        "--measures", f"{name}:{value}"
-    ],
-        check=False
+    subprocess.run(
+        [datadog_cmd, "measure", "--level", "job", "--measures", f"{name}:{value}"],
+        check=False,
     )
 
 
 if __name__ == "__main__":
-    parser = argparse.ArgumentParser(
-        prog="DataDog metric uploader"
-    )
+    parser = argparse.ArgumentParser(prog="DataDog metric uploader")
     parser.add_argument("cpu-usage-history-csv")
     args = parser.parse_args()
 
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index 1e6a008a5de..9fce68947f4 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -53,7 +53,8 @@ function isLinux {
 }
 
 function isKnownToBeMingwBuild {
-    isGitHubActions && [[ "${CI_JOB_NAME}" == *mingw ]]
+    # CI_JOB_NAME must end with "mingw" and optionally `-N` to be considered a MinGW build.
+    isGitHubActions && [[ "${CI_JOB_NAME}" =~ mingw(-[0-9]+)?$ ]]
 }
 
 function isCiBranch {
diff --git a/src/doc/book b/src/doc/book
-Subproject e16dd73690a6cc3ecdc5f5d94bbc3ce158a42e1
+Subproject 9900d976bbfecf4e8124da54351a9ad85ee3c7f
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject f48b0e842a3911c63240e955d042089e9e0894c
+Subproject 128669297c8a7fdf771042eaec18b8adfaeaf0c
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 5c86c739ec71b8bc839310ff47fa94e94635bba
+Subproject ede56d1bbe132bac476b5029cd6d7508ca9572e
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 787b4166ccc67bd8f72a6e3ef6685ce9ce82909
+Subproject b21d99b770f9aceb0810c843847c52f86f45d2e
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 243cb3b2fc8..3b82d123276 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -344,15 +344,15 @@ target | std | host | notes
 [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ |  |
 [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
-`powerpc64le-unknown-freebsd` |   |   | PPC64LE FreeBSD
-`powerpc-unknown-freebsd` |   |   | PowerPC FreeBSD
+`powerpc64le-unknown-freebsd` | ✓ | ✓ | PPC64LE FreeBSD
+`powerpc-unknown-freebsd` | ? |   | PowerPC FreeBSD
 `powerpc64-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3
 [`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 `powerpc64le-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3, Little Endian
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
 [`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
-`riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
-`riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches)
+`riscv32gc-unknown-linux-gnu` | ✓ |   | RISC-V Linux (kernel 5.4, glibc 2.33)
+`riscv32gc-unknown-linux-musl` | ? |   | RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches)
 [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? |  | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA)
 [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * |  | Bare RISC-V (RV32IMA ISA)
 [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? |  | RISC-V Xous (RV32IMAC ISA)
@@ -361,13 +361,13 @@ target | std | host | notes
 [`riscv32imafc-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
 [`riscv32-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ |   | RISC-V Hermit
-`riscv64gc-unknown-freebsd` |   |   | RISC-V FreeBSD
-`riscv64gc-unknown-fuchsia` |   |   | RISC-V Fuchsia
+`riscv64gc-unknown-freebsd` | ? |   | RISC-V FreeBSD
+`riscv64gc-unknown-fuchsia` | ? |   | RISC-V Fuchsia
 [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
 [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
-[`riscv64-linux-android`](platform-support/android.md) |   |   | RISC-V 64-bit Android
+[`riscv64-linux-android`](platform-support/android.md) | ? |   | RISC-V 64-bit Android
 [`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
-[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) |  |  | S390x Linux (kernel 3.2, musl 1.2.3)
+[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ |  | S390x Linux (kernel 3.2, musl 1.2.3)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
 [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * |  | Bare 32-bit SPARC V7+
 [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64
diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
index e7e3fd01c4d..3c3e35a51b8 100644
--- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
+++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
@@ -16,7 +16,7 @@ BE8 architecture is the default big-endian architecture for Arm since [Armv6](ht
 The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard Arm configuration).
 
 ## Target definition
-The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required.
+The target definition can be seen [here](https://github.com/rust-lang/rust/blob/master/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required.
 
 ## Building the target
 Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.
diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
index 60e06c404c0..6f09ce42dbb 100644
--- a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
+++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
@@ -64,6 +64,22 @@ There are no special requirements for testing and running the target.
 For testing cross builds on the host, please refer to the "Cross-compilation
 toolchains and C code" section below.
 
+If you want to do native testing but do not have your own s390x
+machine, there are several options how to get access to one:
+
+* The [IBM LinuxONE Community Cloud][cloud-community] provides a
+  self-service portal where you can create s390x virtual machine
+  instances.  These are intended for temporary use (limited to 120 days).
+
+* The [IBM LinuxONE Open Source Cloud][cloud-opensource] provides
+  permanent access to s390x machines.  This requires approval by IBM,
+  which will normally be granted if you're planning to use the machine
+  to work on an open-source project that is relevant to the IBM Z
+  ecosystem - the Rust compiler would certainly qualify.
+
+[cloud-community]: https://linuxone.cloud.marist.edu/
+[cloud-opensource]: https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/
+
 ## Cross-compilation toolchains and C code
 
 Rust code built using the target is compatible with C code compiled with
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index e9524c0b78d..db8426492ee 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -47,6 +47,10 @@ It can be enabled using:
 #![deny(rustdoc::missing_doc_code_examples)]
 ```
 
+It is not emitted for items that cannot be instantiated/called such as fields, variants, modules,
+associated trait/impl items, impl blocks, statics and constants.
+It is also not emitted for foreign items, aliases, extern crates and imports.
+
 ## Extensions to the `#[doc]` attribute
 
 These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler
diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md
new file mode 100644
index 00000000000..bea667dcf44
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md
@@ -0,0 +1,7 @@
+# `debug-info-type-line-numbers`
+
+---
+
+This option causes additional type and line information to be emitted in debug
+info to provide richer information to debuggers. This is currently off by
+default as it causes some compilation scenarios to be noticeably slower.
diff --git a/src/doc/unstable-book/src/compiler-flags/randomize-layout.md b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md
new file mode 100644
index 00000000000..84c6712bc23
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md
@@ -0,0 +1,23 @@
+# `randomize-layout`
+
+The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764).
+
+------------------------
+
+The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal
+optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified
+default representation. This also affects type sizes and padding.
+Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized.
+
+It can be used to find unsafe code that accidentally relies on unspecified behavior.
+
+Randomization is not guaranteed to use a different permutation for each compilation session.
+`-Zlayout-seed=<u64>` can be used to supply additional entropy.
+
+Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently
+result in the same layout due to limitations of the current implementation. Randomization may become
+more aggressive over time as our coverage of the available degrees of freedoms improves.
+Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds
+on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts.
+
+Randomization may also become less aggressive in the future if additional guarantees get added to the default layout.
diff --git a/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md b/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md
new file mode 100644
index 00000000000..35b782f38dc
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md
@@ -0,0 +1,15 @@
+# `reg-struct-return`
+
+The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116973.
+
+------------------------
+
+Option -Zreg-struct-return causes the compiler to return small structs in registers
+instead of on the stack for extern "C"-like functions.
+It is UNSOUND to link together crates that use different values for this flag.
+It is only supported on `x86`.
+
+It is equivalent to [Clang]'s and [GCC]'s `-freg-struct-return`.
+
+[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-freg-struct-return
+[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-freg-struct-return
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 12a73f0508b..c2f4170d7d2 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -34,7 +34,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`          | `r0`, `r[3-12]`, `r[14-28]`        | `r`                  |
 | PowerPC      | `reg_nonzero`  | `r[3-12]`, `r[14-28]`              | `b`                  |
 | PowerPC      | `freg`         | `f[0-31]`                          | `f`                  |
-| PowerPC      | `vreg`         | `v[0-31]`                          | Only clobbers        |
+| PowerPC      | `vreg`         | `v[0-31]`                          | `v`                  |
 | PowerPC      | `cr`           | `cr[0-7]`, `cr`                    | Only clobbers        |
 | PowerPC      | `xer`          | `xer`                              | Only clobbers        |
 | wasm32       | `local`        | None\*                             | `r`                  |
@@ -75,7 +75,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `reg_nonzero`                   | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `freg`                          | None           | `f32`, `f64`                            |
-| PowerPC      | `vreg`                          | N/A            | Only clobbers                           |
+| PowerPC      | `vreg`                          | `altivec`      | `i8x16`, `i16x8`, `i32x4`, `f32x4`      |
+| PowerPC      | `vreg`                          | `vsx`          | `f32`, `f64`, `i64x2`, `f64x2`          |
 | PowerPC      | `cr`                            | N/A            | Only clobbers                           |
 | PowerPC      | `xer`                           | N/A            | Only clobbers                           |
 | wasm32       | `local`                         | None           | `i8` `i16` `i32` `i64` `f32` `f64`      |
@@ -181,6 +182,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`          | None     | `0`            | None          |
 | PowerPC      | `reg_nonzero`  | None     | `3`            | None          |
 | PowerPC      | `freg`         | None     | `0`            | None          |
+| PowerPC      | `vreg`         | None     | `0`            | None          |
 | SPARC        | `reg`          | None     | `%o0`          | None          |
 | CSKY         | `reg`          | None     | `r0`           | None          |
 | CSKY         | `freg`         | None     | `f0`           | None          |
diff --git a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md b/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md
deleted file mode 100644
index b20c30ec8f1..00000000000
--- a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# `extended_varargs_abi_support`
-
-The tracking issue for this feature is: [#100189]
-
-[#100189]: https://github.com/rust-lang/rust/issues/100189
-
-------------------------
-
-This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling
-conventions on functions with varargs.
diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py
index 9264a8439bb..791186de9c1 100755
--- a/src/etc/dec2flt_table.py
+++ b/src/etc/dec2flt_table.py
@@ -13,6 +13,7 @@ i.e., within 0.5 ULP of the true value.
 Adapted from Daniel Lemire's fast_float ``table_generation.py``,
 available here: <https://github.com/fastfloat/fast_float/blob/main/script/table_generation.py>.
 """
+
 from __future__ import print_function
 from math import ceil, floor, log
 from collections import deque
@@ -34,6 +35,7 @@ STATIC_WARNING = """
 // the final binary.
 """
 
+
 def main():
     min_exp = minimum_exponent(10)
     max_exp = maximum_exponent(10)
@@ -41,10 +43,10 @@ def main():
 
     print(HEADER.strip())
     print()
-    print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp))
-    print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp))
-    print('pub const N_POWERS_OF_FIVE: usize = ', end='')
-    print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;')
+    print("pub const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp))
+    print("pub const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp))
+    print("pub const N_POWERS_OF_FIVE: usize = ", end="")
+    print("(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;")
     print()
     print_proper_powers(min_exp, max_exp, bias)
 
@@ -54,7 +56,7 @@ def minimum_exponent(base):
 
 
 def maximum_exponent(base):
-    return floor(log(1.7976931348623157e+308, base))
+    return floor(log(1.7976931348623157e308, base))
 
 
 def print_proper_powers(min_exp, max_exp, bias):
@@ -64,46 +66,46 @@ def print_proper_powers(min_exp, max_exp, bias):
     # 2^(2b)/(5^−q) with b=64 + int(math.ceil(log2(5^−q)))
     powers = []
     for q in range(min_exp, 0):
-        power5 = 5 ** -q
+        power5 = 5**-q
         z = 0
         while (1 << z) < power5:
             z += 1
         if q >= -27:
             b = z + 127
-            c = 2 ** b // power5 + 1
+            c = 2**b // power5 + 1
             powers.append((c, q))
         else:
             b = 2 * z + 2 * 64
-            c = 2 ** b // power5 + 1
+            c = 2**b // power5 + 1
             # truncate
-            while c >= (1<<128):
+            while c >= (1 << 128):
                 c //= 2
             powers.append((c, q))
 
     # Add positive exponents
     for q in range(0, max_exp + 1):
-        power5 = 5 ** q
+        power5 = 5**q
         # move the most significant bit in position
-        while power5 < (1<<127):
+        while power5 < (1 << 127):
             power5 *= 2
         # *truncate*
-        while power5 >= (1<<128):
+        while power5 >= (1 << 128):
             power5 //= 2
         powers.append((power5, q))
 
     # Print the powers.
     print(STATIC_WARNING.strip())
-    print('#[rustfmt::skip]')
-    typ = '[(u64, u64); N_POWERS_OF_FIVE]'
-    print('pub static POWER_OF_FIVE_128: {} = ['.format(typ))
+    print("#[rustfmt::skip]")
+    typ = "[(u64, u64); N_POWERS_OF_FIVE]"
+    print("pub static POWER_OF_FIVE_128: {} = [".format(typ))
     for c, exp in powers:
-        hi = '0x{:x}'.format(c // (1 << 64))
-        lo = '0x{:x}'.format(c % (1 << 64))
-        value = '    ({}, {}), '.format(hi, lo)
-        comment = '// {}^{}'.format(5, exp)
-        print(value.ljust(46, ' ') + comment)
-    print('];')
+        hi = "0x{:x}".format(c // (1 << 64))
+        lo = "0x{:x}".format(c % (1 << 64))
+        value = "    ({}, {}), ".format(hi, lo)
+        comment = "// {}^{}".format(5, exp)
+        print(value.ljust(46, " ") + comment)
+    print("];")
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py
index e05039ce474..73d1e79f961 100644
--- a/src/etc/gdb_load_rust_pretty_printers.py
+++ b/src/etc/gdb_load_rust_pretty_printers.py
@@ -1,6 +1,7 @@
 # Add this folder to the python sys path; GDB Python-interpreter will now find modules in this path
 import sys
 from os import path
+
 self_dir = path.dirname(path.realpath(__file__))
 sys.path.append(self_dir)
 
diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py
index f3ac9c10978..d368f7ed1ec 100644
--- a/src/etc/gdb_lookup.py
+++ b/src/etc/gdb_lookup.py
@@ -6,8 +6,11 @@ from gdb_providers import *
 from rust_types import *
 
 
-_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
-gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
+_gdb_version_matched = re.search("([0-9]+)\\.([0-9]+)", gdb.VERSION)
+gdb_version = (
+    [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
+)
+
 
 def register_printers(objfile):
     objfile.pretty_printers.append(printer)
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index e8f9dee07d3..34bb5c39909 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -21,7 +21,7 @@ def unwrap_unique_or_non_null(unique_or_nonnull):
 # GDB 14 has a tag class that indicates that extension methods are ok
 # to call.  Use of this tag only requires that printers hide local
 # attributes and methods by prefixing them with "_".
-if hasattr(gdb, 'ValuePrinter'):
+if hasattr(gdb, "ValuePrinter"):
     printer_base = gdb.ValuePrinter
 else:
     printer_base = object
@@ -98,7 +98,7 @@ class StdStrProvider(printer_base):
 
 
 def _enumerate_array_elements(element_ptrs):
-    for (i, element_ptr) in enumerate(element_ptrs):
+    for i, element_ptr in enumerate(element_ptrs):
         key = "[{}]".format(i)
         element = element_ptr.dereference()
 
@@ -173,7 +173,8 @@ class StdVecDequeProvider(printer_base):
 
     def children(self):
         return _enumerate_array_elements(
-            (self._data_ptr + ((self._head + index) % self._cap)) for index in xrange(self._size)
+            (self._data_ptr + ((self._head + index) % self._cap))
+            for index in xrange(self._size)
         )
 
     @staticmethod
@@ -270,7 +271,9 @@ def children_of_btree_map(map):
     # Yields each key/value pair in the node and in any child nodes.
     def children_of_node(node_ptr, height):
         def cast_to_internal(node):
-            internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
+            internal_type_name = node.type.target().name.replace(
+                "LeafNode", "InternalNode", 1
+            )
             internal_type = gdb.lookup_type(internal_type_name)
             return node.cast(internal_type.pointer())
 
@@ -293,8 +296,16 @@ def children_of_btree_map(map):
                 # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
                 key_type_size = keys.type.sizeof
                 val_type_size = vals.type.sizeof
-                key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()")
-                val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()")
+                key = (
+                    keys[i]["value"]["value"]
+                    if key_type_size > 0
+                    else gdb.parse_and_eval("()")
+                )
+                val = (
+                    vals[i]["value"]["value"]
+                    if val_type_size > 0
+                    else gdb.parse_and_eval("()")
+                )
                 yield key, val
 
     if map["length"] > 0:
@@ -352,7 +363,7 @@ class StdOldHashMapProvider(printer_base):
         self._hashes = self._table["hashes"]
         self._hash_uint_type = self._hashes.type
         self._hash_uint_size = self._hashes.type.sizeof
-        self._modulo = 2 ** self._hash_uint_size
+        self._modulo = 2**self._hash_uint_size
         self._data_ptr = self._hashes[ZERO_FIELD]["pointer"]
 
         self._capacity_mask = int(self._table["capacity_mask"])
@@ -382,8 +393,14 @@ class StdOldHashMapProvider(printer_base):
 
         hashes = self._hash_uint_size * self._capacity
         align = self._pair_type_size
-        len_rounded_up = (((((hashes + align) % self._modulo - 1) % self._modulo) & ~(
-                (align - 1) % self._modulo)) % self._modulo - hashes) % self._modulo
+        len_rounded_up = (
+            (
+                (((hashes + align) % self._modulo - 1) % self._modulo)
+                & ~((align - 1) % self._modulo)
+            )
+            % self._modulo
+            - hashes
+        ) % self._modulo
 
         pairs_offset = hashes + len_rounded_up
         pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer())
diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py
index d61693460bc..2e810d7df97 100755
--- a/src/etc/generate-deriving-span-tests.py
+++ b/src/etc/generate-deriving-span-tests.py
@@ -12,7 +12,8 @@ import os
 import stat
 
 TEST_DIR = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))
+    os.path.join(os.path.dirname(__file__), "../test/ui/derives/")
+)
 
 TEMPLATE = """\
 // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
@@ -56,28 +57,33 @@ ENUM_TUPLE, ENUM_STRUCT, STRUCT_FIELDS, STRUCT_TUPLE = range(4)
 
 
 def create_test_case(type, trait, super_traits, error_count):
-    string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type]
-    all_traits = ','.join([trait] + super_traits)
-    super_traits = ','.join(super_traits)
-    error_deriving = '#[derive(%s)]' % super_traits if super_traits else ''
-
-    errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count))
+    string = [
+        ENUM_STRING,
+        ENUM_STRUCT_VARIANT_STRING,
+        STRUCT_STRING,
+        STRUCT_TUPLE_STRING,
+    ][type]
+    all_traits = ",".join([trait] + super_traits)
+    super_traits = ",".join(super_traits)
+    error_deriving = "#[derive(%s)]" % super_traits if super_traits else ""
+
+    errors = "\n".join("//~%s ERROR" % ("^" * n) for n in range(error_count))
     code = string.format(traits=all_traits, errors=errors)
     return TEMPLATE.format(error_deriving=error_deriving, code=code)
 
 
 def write_file(name, string):
-    test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name)
+    test_file = os.path.join(TEST_DIR, "derives-span-%s.rs" % name)
 
     # set write permission if file exists, so it can be changed
     if os.path.exists(test_file):
         os.chmod(test_file, stat.S_IWUSR)
 
-    with open(test_file, 'w') as f:
+    with open(test_file, "w") as f:
         f.write(string)
 
     # mark file read-only
-    os.chmod(test_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
+    os.chmod(test_file, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
 
 
 ENUM = 1
@@ -85,29 +91,31 @@ STRUCT = 2
 ALL = STRUCT | ENUM
 
 traits = {
-    'Default': (STRUCT, [], 1),
-    'FromPrimitive': (0, [], 0),  # only works for C-like enums
-
-    'Decodable': (0, [], 0),  # FIXME: quoting gives horrible spans
-    'Encodable': (0, [], 0),  # FIXME: quoting gives horrible spans
+    "Default": (STRUCT, [], 1),
+    "FromPrimitive": (0, [], 0),  # only works for C-like enums
+    "Decodable": (0, [], 0),  # FIXME: quoting gives horrible spans
+    "Encodable": (0, [], 0),  # FIXME: quoting gives horrible spans
 }
 
-for (trait, supers, errs) in [('Clone', [], 1),
-                              ('PartialEq', [], 2),
-                              ('PartialOrd', ['PartialEq'], 1),
-                              ('Eq', ['PartialEq'], 1),
-                              ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
-                              ('Debug', [], 1),
-                              ('Hash', [], 1)]:
+for trait, supers, errs in [
+    ("Clone", [], 1),
+    ("PartialEq", [], 2),
+    ("PartialOrd", ["PartialEq"], 1),
+    ("Eq", ["PartialEq"], 1),
+    ("Ord", ["Eq", "PartialOrd", "PartialEq"], 1),
+    ("Debug", [], 1),
+    ("Hash", [], 1),
+]:
     traits[trait] = (ALL, supers, errs)
 
-for (trait, (types, super_traits, error_count)) in traits.items():
+for trait, (types, super_traits, error_count) in traits.items():
+
     def mk(ty, t=trait, st=super_traits, ec=error_count):
         return create_test_case(ty, t, st, ec)
 
     if types & ENUM:
-        write_file(trait + '-enum', mk(ENUM_TUPLE))
-        write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT))
+        write_file(trait + "-enum", mk(ENUM_TUPLE))
+        write_file(trait + "-enum-struct-variant", mk(ENUM_STRUCT))
     if types & STRUCT:
-        write_file(trait + '-struct', mk(STRUCT_FIELDS))
-        write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE))
+        write_file(trait + "-struct", mk(STRUCT_FIELDS))
+        write_file(trait + "-tuple-struct", mk(STRUCT_TUPLE))
diff --git a/src/etc/generate-keyword-tests.py b/src/etc/generate-keyword-tests.py
index 77c3d2758c6..28f932acd9d 100755
--- a/src/etc/generate-keyword-tests.py
+++ b/src/etc/generate-keyword-tests.py
@@ -22,18 +22,16 @@ fn main() {
 }
 """
 
-test_dir = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '../test/ui/parser')
-)
+test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../test/ui/parser"))
 
 for kw in sys.argv[1:]:
-    test_file = os.path.join(test_dir, 'keyword-%s-as-identifier.rs' % kw)
+    test_file = os.path.join(test_dir, "keyword-%s-as-identifier.rs" % kw)
 
     # set write permission if file exists, so it can be changed
     if os.path.exists(test_file):
         os.chmod(test_file, stat.S_IWUSR)
 
-    with open(test_file, 'wt') as f:
+    with open(test_file, "wt") as f:
         f.write(template % (kw, kw, kw))
 
     # mark file read-only
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 851b01a7458..d6b594aca71 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -127,6 +127,7 @@ import os.path
 import re
 import shlex
 from collections import namedtuple
+
 try:
     from html.parser import HTMLParser
 except ImportError:
@@ -142,12 +143,28 @@ except ImportError:
     from htmlentitydefs import name2codepoint
 
 # "void elements" (no closing tag) from the HTML Standard section 12.1.2
-VOID_ELEMENTS = {'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
-                     'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'}
+VOID_ELEMENTS = {
+    "area",
+    "base",
+    "br",
+    "col",
+    "embed",
+    "hr",
+    "img",
+    "input",
+    "keygen",
+    "link",
+    "menuitem",
+    "meta",
+    "param",
+    "source",
+    "track",
+    "wbr",
+}
 
 # Python 2 -> 3 compatibility
 try:
-    unichr # noqa: B018 FIXME: py2
+    unichr  # noqa: B018 FIXME: py2
 except NameError:
     unichr = chr
 
@@ -158,18 +175,20 @@ channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
 rust_test_path = None
 bless = None
 
+
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
 
     this is possible because we are dealing with very regular HTML from
     rustdoc; we only have to deal with i) void elements and ii) empty
     attributes."""
+
     def __init__(self, target=None):
         HTMLParser.__init__(self)
         self.__builder = target or ET.TreeBuilder()
 
     def handle_starttag(self, tag, attrs):
-        attrs = {k: v or '' for k, v in attrs}
+        attrs = {k: v or "" for k, v in attrs}
         self.__builder.start(tag, attrs)
         if tag in VOID_ELEMENTS:
             self.__builder.end(tag)
@@ -178,7 +197,7 @@ class CustomHTMLParser(HTMLParser):
         self.__builder.end(tag)
 
     def handle_startendtag(self, tag, attrs):
-        attrs = {k: v or '' for k, v in attrs}
+        attrs = {k: v or "" for k, v in attrs}
         self.__builder.start(tag, attrs)
         self.__builder.end(tag)
 
@@ -189,7 +208,7 @@ class CustomHTMLParser(HTMLParser):
         self.__builder.data(unichr(name2codepoint[name]))
 
     def handle_charref(self, name):
-        code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10)
+        code = int(name[1:], 16) if name.startswith(("x", "X")) else int(name, 10)
         self.__builder.data(unichr(code))
 
     def close(self):
@@ -197,7 +216,7 @@ class CustomHTMLParser(HTMLParser):
         return self.__builder.close()
 
 
-Command = namedtuple('Command', 'negated cmd args lineno context')
+Command = namedtuple("Command", "negated cmd args lineno context")
 
 
 class FailedCheck(Exception):
@@ -216,17 +235,17 @@ def concat_multi_lines(f):
       concatenated."""
     lastline = None  # set to the last line when the last line has a backslash
     firstlineno = None
-    catenated = ''
+    catenated = ""
     for lineno, line in enumerate(f):
-        line = line.rstrip('\r\n')
+        line = line.rstrip("\r\n")
 
         # strip the common prefix from the current line if needed
         if lastline is not None:
             common_prefix = os.path.commonprefix([line, lastline])
-            line = line[len(common_prefix):].lstrip()
+            line = line[len(common_prefix) :].lstrip()
 
         firstlineno = firstlineno or lineno
-        if line.endswith('\\'):
+        if line.endswith("\\"):
             if lastline is None:
                 lastline = line[:-1]
             catenated += line[:-1]
@@ -234,10 +253,10 @@ def concat_multi_lines(f):
             yield firstlineno, catenated + line
             lastline = None
             firstlineno = None
-            catenated = ''
+            catenated = ""
 
     if lastline is not None:
-        print_err(lineno, line, 'Trailing backslash at the end of the file')
+        print_err(lineno, line, "Trailing backslash at the end of the file")
 
 
 def get_known_directive_names():
@@ -253,12 +272,12 @@ def get_known_directive_names():
             "tools/compiletest/src/directive-list.rs",
         ),
         "r",
-        encoding="utf8"
+        encoding="utf8",
     ) as fd:
         content = fd.read()
         return [
-            line.strip().replace('",', '').replace('"', '')
-            for line in content.split('\n')
+            line.strip().replace('",', "").replace('"', "")
+            for line in content.split("\n")
             if filter_line(line)
         ]
 
@@ -269,35 +288,42 @@ def get_known_directive_names():
 #        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
 KNOWN_DIRECTIVE_NAMES = get_known_directive_names()
 
-LINE_PATTERN = re.compile(r'''
+LINE_PATTERN = re.compile(
+    r"""
     //@\s+
     (?P<negated>!?)(?P<cmd>[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)
     (?P<args>.*)$
-''', re.X | re.UNICODE)
+""",
+    re.X | re.UNICODE,
+)
 
 
 def get_commands(template):
-    with io.open(template, encoding='utf-8') as f:
+    with io.open(template, encoding="utf-8") as f:
         for lineno, line in concat_multi_lines(f):
             m = LINE_PATTERN.search(line)
             if not m:
                 continue
 
-            cmd = m.group('cmd')
-            negated = (m.group('negated') == '!')
+            cmd = m.group("cmd")
+            negated = m.group("negated") == "!"
             if not negated and cmd in KNOWN_DIRECTIVE_NAMES:
                 continue
-            args = m.group('args')
+            args = m.group("args")
             if args and not args[:1].isspace():
-                print_err(lineno, line, 'Invalid template syntax')
+                print_err(lineno, line, "Invalid template syntax")
                 continue
             try:
                 args = shlex.split(args)
             except UnicodeEncodeError:
-                args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))]
+                args = [
+                    arg.decode("utf-8") for arg in shlex.split(args.encode("utf-8"))
+                ]
             except Exception as exc:
                 raise Exception("line {}: {}".format(lineno + 1, exc)) from None
-            yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line)
+            yield Command(
+                negated=negated, cmd=cmd, args=args, lineno=lineno + 1, context=line
+            )
 
 
 def _flatten(node, acc):
@@ -312,22 +338,24 @@ def _flatten(node, acc):
 def flatten(node):
     acc = []
     _flatten(node, acc)
-    return ''.join(acc)
+    return "".join(acc)
 
 
 def make_xml(text):
-    xml = ET.XML('<xml>%s</xml>' % text)
+    xml = ET.XML("<xml>%s</xml>" % text)
     return xml
 
 
 def normalize_xpath(path):
     path = path.replace("{{channel}}", channel)
-    if path.startswith('//'):
-        return '.' + path  # avoid warnings
-    elif path.startswith('.//'):
+    if path.startswith("//"):
+        return "." + path  # avoid warnings
+    elif path.startswith(".//"):
         return path
     else:
-        raise InvalidCheck('Non-absolute XPath is not supported due to implementation issues')
+        raise InvalidCheck(
+            "Non-absolute XPath is not supported due to implementation issues"
+        )
 
 
 class CachedFiles(object):
@@ -338,12 +366,12 @@ class CachedFiles(object):
         self.last_path = None
 
     def resolve_path(self, path):
-        if path != '-':
+        if path != "-":
             path = os.path.normpath(path)
             self.last_path = path
             return path
         elif self.last_path is None:
-            raise InvalidCheck('Tried to use the previous path in the first command')
+            raise InvalidCheck("Tried to use the previous path in the first command")
         else:
             return self.last_path
 
@@ -356,10 +384,10 @@ class CachedFiles(object):
             return self.files[path]
 
         abspath = self.get_absolute_path(path)
-        if not(os.path.exists(abspath) and os.path.isfile(abspath)):
-            raise FailedCheck('File does not exist {!r}'.format(path))
+        if not (os.path.exists(abspath) and os.path.isfile(abspath)):
+            raise FailedCheck("File does not exist {!r}".format(path))
 
-        with io.open(abspath, encoding='utf-8') as f:
+        with io.open(abspath, encoding="utf-8") as f:
             data = f.read()
             self.files[path] = data
             return data
@@ -370,15 +398,15 @@ class CachedFiles(object):
             return self.trees[path]
 
         abspath = self.get_absolute_path(path)
-        if not(os.path.exists(abspath) and os.path.isfile(abspath)):
-            raise FailedCheck('File does not exist {!r}'.format(path))
+        if not (os.path.exists(abspath) and os.path.isfile(abspath)):
+            raise FailedCheck("File does not exist {!r}".format(path))
 
-        with io.open(abspath, encoding='utf-8') as f:
+        with io.open(abspath, encoding="utf-8") as f:
             try:
                 tree = ET.fromstringlist(f.readlines(), CustomHTMLParser())
             except Exception as e:
-                raise RuntimeError( # noqa: B904 FIXME: py2
-                    'Cannot parse an HTML file {!r}: {}'.format(path, e)
+                raise RuntimeError(  # noqa: B904 FIXME: py2
+                    "Cannot parse an HTML file {!r}: {}".format(path, e)
                 )
             self.trees[path] = tree
             return self.trees[path]
@@ -386,8 +414,8 @@ class CachedFiles(object):
     def get_dir(self, path):
         path = self.resolve_path(path)
         abspath = self.get_absolute_path(path)
-        if not(os.path.exists(abspath) and os.path.isdir(abspath)):
-            raise FailedCheck('Directory does not exist {!r}'.format(path))
+        if not (os.path.exists(abspath) and os.path.isdir(abspath)):
+            raise FailedCheck("Directory does not exist {!r}".format(path))
 
 
 def check_string(data, pat, regexp):
@@ -397,8 +425,8 @@ def check_string(data, pat, regexp):
     elif regexp:
         return re.search(pat, data, flags=re.UNICODE) is not None
     else:
-        data = ' '.join(data.split())
-        pat = ' '.join(pat.split())
+        data = " ".join(data.split())
+        pat = " ".join(pat.split())
         return pat in data
 
 
@@ -444,19 +472,19 @@ def get_tree_count(tree, path):
 
 
 def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
-    assert rust_test_path.endswith('.rs')
-    snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
+    assert rust_test_path.endswith(".rs")
+    snapshot_path = "{}.{}.{}".format(rust_test_path[:-3], snapshot_name, "html")
     try:
-        with open(snapshot_path, 'r') as snapshot_file:
+        with open(snapshot_path, "r") as snapshot_file:
             expected_str = snapshot_file.read().replace("{{channel}}", channel)
     except FileNotFoundError:
         if bless:
             expected_str = None
         else:
-            raise FailedCheck('No saved snapshot value') # noqa: B904 FIXME: py2
+            raise FailedCheck("No saved snapshot value")  # noqa: B904 FIXME: py2
 
     if not normalize_to_text:
-        actual_str = ET.tostring(actual_tree).decode('utf-8')
+        actual_str = ET.tostring(actual_tree).decode("utf-8")
     else:
         actual_str = flatten(actual_tree)
 
@@ -464,64 +492,66 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
     #  1. Is --bless
     #  2. Are actual and expected tree different
     #  3. Are actual and expected text different
-    if not expected_str \
-        or (not normalize_to_text and \
-            not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
-        or (normalize_to_text and actual_str != expected_str):
-
+    if (
+        not expected_str
+        or (
+            not normalize_to_text
+            and not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)
+        )
+        or (normalize_to_text and actual_str != expected_str)
+    ):
         if bless:
-            with open(snapshot_path, 'w') as snapshot_file:
+            with open(snapshot_path, "w") as snapshot_file:
                 actual_str = actual_str.replace(channel, "{{channel}}")
                 snapshot_file.write(actual_str)
         else:
-            print('--- expected ---\n')
+            print("--- expected ---\n")
             print(expected_str)
-            print('\n\n--- actual ---\n')
+            print("\n\n--- actual ---\n")
             print(actual_str)
             print()
-            raise FailedCheck('Actual snapshot value is different than expected')
+            raise FailedCheck("Actual snapshot value is different than expected")
 
 
 # Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
 def compare_tree(x1, x2, reporter=None):
     if x1.tag != x2.tag:
         if reporter:
-            reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
+            reporter("Tags do not match: %s and %s" % (x1.tag, x2.tag))
         return False
     for name, value in x1.attrib.items():
         if x2.attrib.get(name) != value:
             if reporter:
-                reporter('Attributes do not match: %s=%r, %s=%r'
-                         % (name, value, name, x2.attrib.get(name)))
+                reporter(
+                    "Attributes do not match: %s=%r, %s=%r"
+                    % (name, value, name, x2.attrib.get(name))
+                )
             return False
     for name in x2.attrib:
         if name not in x1.attrib:
             if reporter:
-                reporter('x2 has an attribute x1 is missing: %s'
-                         % name)
+                reporter("x2 has an attribute x1 is missing: %s" % name)
             return False
     if not text_compare(x1.text, x2.text):
         if reporter:
-            reporter('text: %r != %r' % (x1.text, x2.text))
+            reporter("text: %r != %r" % (x1.text, x2.text))
         return False
     if not text_compare(x1.tail, x2.tail):
         if reporter:
-            reporter('tail: %r != %r' % (x1.tail, x2.tail))
+            reporter("tail: %r != %r" % (x1.tail, x2.tail))
         return False
     cl1 = list(x1)
     cl2 = list(x2)
     if len(cl1) != len(cl2):
         if reporter:
-            reporter('children length differs, %i != %i'
-                     % (len(cl1), len(cl2)))
+            reporter("children length differs, %i != %i" % (len(cl1), len(cl2)))
         return False
     i = 0
     for c1, c2 in zip(cl1, cl2):
         i += 1
         if not compare_tree(c1, c2, reporter=reporter):
             if reporter:
-                reporter('children %i do not match: %s'
-                         % (i, c1.tag))
+                reporter("children %i do not match: %s" % (i, c1.tag))
             return False
     return True
 
@@ -529,14 +559,14 @@ def compare_tree(x1, x2, reporter=None):
 def text_compare(t1, t2):
     if not t1 and not t2:
         return True
-    if t1 == '*' or t2 == '*':
+    if t1 == "*" or t2 == "*":
         return True
-    return (t1 or '').strip() == (t2 or '').strip()
+    return (t1 or "").strip() == (t2 or "").strip()
 
 
 def stderr(*args):
     if sys.version_info.major < 3:
-        file = codecs.getwriter('utf-8')(sys.stderr)
+        file = codecs.getwriter("utf-8")(sys.stderr)
     else:
         file = sys.stderr
 
@@ -556,21 +586,25 @@ def print_err(lineno, context, err, message=None):
 
 def get_nb_matching_elements(cache, c, regexp, stop_at_first):
     tree = cache.get_tree(c.args[0])
-    pat, sep, attr = c.args[1].partition('/@')
+    pat, sep, attr = c.args[1].partition("/@")
     if sep:  # attribute
         tree = cache.get_tree(c.args[0])
         return check_tree_attr(tree, pat, attr, c.args[2], False)
     else:  # normalized text
         pat = c.args[1]
-        if pat.endswith('/text()'):
+        if pat.endswith("/text()"):
             pat = pat[:-7]
-        return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
+        return check_tree_text(
+            cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first
+        )
 
 
 def check_files_in_folder(c, cache, folder, files):
     files = files.strip()
-    if not files.startswith('[') or not files.endswith(']'):
-        raise InvalidCheck("Expected list as second argument of {} (ie '[]')".format(c.cmd))
+    if not files.startswith("[") or not files.endswith("]"):
+        raise InvalidCheck(
+            "Expected list as second argument of {} (ie '[]')".format(c.cmd)
+        )
 
     folder = cache.get_absolute_path(folder)
 
@@ -592,12 +626,18 @@ def check_files_in_folder(c, cache, folder, files):
 
     error = 0
     if len(files_set) != 0:
-        print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format(
-            folder, files_set))
+        print_err(
+            c.lineno,
+            c.context,
+            "Entries not found in folder `{}`: `{}`".format(folder, files_set),
+        )
         error += 1
     if len(folder_set) != 0:
-        print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format(
-            folder, folder_set))
+        print_err(
+            c.lineno,
+            c.context,
+            "Extra entries in folder `{}`: `{}`".format(folder, folder_set),
+        )
         error += 1
     return error == 0
 
@@ -608,11 +648,11 @@ ERR_COUNT = 0
 def check_command(c, cache):
     try:
         cerr = ""
-        if c.cmd in ['has', 'hasraw', 'matches', 'matchesraw']:  # string test
-            regexp = c.cmd.startswith('matches')
+        if c.cmd in ["has", "hasraw", "matches", "matchesraw"]:  # string test
+            regexp = c.cmd.startswith("matches")
 
             # has <path> = file existence
-            if len(c.args) == 1 and not regexp and 'raw' not in c.cmd:
+            if len(c.args) == 1 and not regexp and "raw" not in c.cmd:
                 try:
                     cache.get_file(c.args[0])
                     ret = True
@@ -620,24 +660,24 @@ def check_command(c, cache):
                     cerr = str(err)
                     ret = False
             # hasraw/matchesraw <path> <pat> = string test
-            elif len(c.args) == 2 and 'raw' in c.cmd:
+            elif len(c.args) == 2 and "raw" in c.cmd:
                 cerr = "`PATTERN` did not match"
                 ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp)
             # has/matches <path> <pat> <match> = XML tree test
-            elif len(c.args) == 3 and 'raw' not in c.cmd:
+            elif len(c.args) == 3 and "raw" not in c.cmd:
                 cerr = "`XPATH PATTERN` did not match"
                 ret = get_nb_matching_elements(cache, c, regexp, True) != 0
             else:
-                raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
+                raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
 
-        elif c.cmd == 'files': # check files in given folder
-            if len(c.args) != 2: # files <folder path> <file list>
+        elif c.cmd == "files":  # check files in given folder
+            if len(c.args) != 2:  # files <folder path> <file list>
                 raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
             elif c.negated:
                 raise InvalidCheck("{} doesn't support negative check".format(c.cmd))
             ret = check_files_in_folder(c, cache, c.args[0], c.args[1])
 
-        elif c.cmd == 'count':  # count test
+        elif c.cmd == "count":  # count test
             if len(c.args) == 3:  # count <path> <pat> <count> = count test
                 expected = int(c.args[2])
                 found = get_tree_count(cache.get_tree(c.args[0]), c.args[1])
@@ -649,15 +689,15 @@ def check_command(c, cache):
                 cerr = "Expected {} occurrences but found {}".format(expected, found)
                 ret = found == expected
             else:
-                raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
+                raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
 
-        elif c.cmd == 'snapshot':  # snapshot test
+        elif c.cmd == "snapshot":  # snapshot test
             if len(c.args) == 3:  # snapshot <snapshot-name> <html-path> <xpath>
                 [snapshot_name, html_path, pattern] = c.args
                 tree = cache.get_tree(html_path)
                 xpath = normalize_xpath(pattern)
                 normalize_to_text = False
-                if xpath.endswith('/text()'):
+                if xpath.endswith("/text()"):
                     xpath = xpath[:-7]
                     normalize_to_text = True
 
@@ -671,13 +711,15 @@ def check_command(c, cache):
                         cerr = str(err)
                         ret = False
                 elif len(subtrees) == 0:
-                    raise FailedCheck('XPATH did not match')
+                    raise FailedCheck("XPATH did not match")
                 else:
-                    raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees)))
+                    raise FailedCheck(
+                        "Expected 1 match, but found {}".format(len(subtrees))
+                    )
             else:
-                raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
+                raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
 
-        elif c.cmd == 'has-dir':  # has-dir test
+        elif c.cmd == "has-dir":  # has-dir test
             if len(c.args) == 1:  # has-dir <path> = has-dir test
                 try:
                     cache.get_dir(c.args[0])
@@ -686,22 +728,22 @@ def check_command(c, cache):
                     cerr = str(err)
                     ret = False
             else:
-                raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
+                raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
 
-        elif c.cmd == 'valid-html':
-            raise InvalidCheck('Unimplemented valid-html')
+        elif c.cmd == "valid-html":
+            raise InvalidCheck("Unimplemented valid-html")
 
-        elif c.cmd == 'valid-links':
-            raise InvalidCheck('Unimplemented valid-links')
+        elif c.cmd == "valid-links":
+            raise InvalidCheck("Unimplemented valid-links")
 
         else:
-            raise InvalidCheck('Unrecognized {}'.format(c.cmd))
+            raise InvalidCheck("Unrecognized {}".format(c.cmd))
 
         if ret == c.negated:
             raise FailedCheck(cerr)
 
     except FailedCheck as err:
-        message = '{}{} check failed'.format('!' if c.negated else '', c.cmd)
+        message = "{}{} check failed".format("!" if c.negated else "", c.cmd)
         print_err(c.lineno, c.context, str(err), message)
     except InvalidCheck as err:
         print_err(c.lineno, c.context, str(err))
@@ -713,18 +755,18 @@ def check(target, commands):
         check_command(c, cache)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     if len(sys.argv) not in [3, 4]:
-        stderr('Usage: {} <doc dir> <template> [--bless]'.format(sys.argv[0]))
+        stderr("Usage: {} <doc dir> <template> [--bless]".format(sys.argv[0]))
         raise SystemExit(1)
 
     rust_test_path = sys.argv[2]
-    if len(sys.argv) > 3 and sys.argv[3] == '--bless':
+    if len(sys.argv) > 3 and sys.argv[3] == "--bless":
         bless = True
     else:
         # We only support `--bless` at the end of the arguments.
         # This assert is to prevent silent failures.
-        assert '--bless' not in sys.argv
+        assert "--bless" not in sys.argv
         bless = False
     check(sys.argv[1], get_commands(rust_test_path))
     if ERR_COUNT:
diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py
index db1e0035ea0..cf88c53e085 100644
--- a/src/etc/lldb_batchmode.py
+++ b/src/etc/lldb_batchmode.py
@@ -45,7 +45,7 @@ def normalize_whitespace(s):
 
 def breakpoint_callback(frame, bp_loc, dict):
     """This callback is registered with every breakpoint and makes sure that the
-    frame containing the breakpoint location is selected """
+    frame containing the breakpoint location is selected"""
 
     # HACK(eddyb) print a newline to avoid continuing an unfinished line.
     print("")
@@ -79,7 +79,7 @@ def execute_command(command_interpreter, command):
 
     if res.Succeeded():
         if res.HasResult():
-            print(normalize_whitespace(res.GetOutput() or ''), end='\n')
+            print(normalize_whitespace(res.GetOutput() or ""), end="\n")
 
         # If the command introduced any breakpoints, make sure to register
         # them with the breakpoint
@@ -89,20 +89,32 @@ def execute_command(command_interpreter, command):
             breakpoint_id = new_breakpoints.pop()
 
             if breakpoint_id in registered_breakpoints:
-                print_debug("breakpoint with id %s is already registered. Ignoring." %
-                            str(breakpoint_id))
+                print_debug(
+                    "breakpoint with id %s is already registered. Ignoring."
+                    % str(breakpoint_id)
+                )
             else:
-                print_debug("registering breakpoint callback, id = " + str(breakpoint_id))
-                callback_command = ("breakpoint command add -F breakpoint_callback " +
-                                    str(breakpoint_id))
+                print_debug(
+                    "registering breakpoint callback, id = " + str(breakpoint_id)
+                )
+                callback_command = (
+                    "breakpoint command add -F breakpoint_callback "
+                    + str(breakpoint_id)
+                )
                 command_interpreter.HandleCommand(callback_command, res)
                 if res.Succeeded():
-                    print_debug("successfully registered breakpoint callback, id = " +
-                                str(breakpoint_id))
+                    print_debug(
+                        "successfully registered breakpoint callback, id = "
+                        + str(breakpoint_id)
+                    )
                     registered_breakpoints.add(breakpoint_id)
                 else:
-                    print("Error while trying to register breakpoint callback, id = " +
-                          str(breakpoint_id) + ", message = " + str(res.GetError()))
+                    print(
+                        "Error while trying to register breakpoint callback, id = "
+                        + str(breakpoint_id)
+                        + ", message = "
+                        + str(res.GetError())
+                    )
     else:
         print(res.GetError())
 
@@ -117,14 +129,16 @@ def start_breakpoint_listener(target):
         try:
             while True:
                 if listener.WaitForEvent(120, event):
-                    if lldb.SBBreakpoint.EventIsBreakpointEvent(event) and \
-                            lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == \
-                            lldb.eBreakpointEventTypeAdded:
+                    if (
+                        lldb.SBBreakpoint.EventIsBreakpointEvent(event)
+                        and lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)
+                        == lldb.eBreakpointEventTypeAdded
+                    ):
                         global new_breakpoints
                         breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event)
                         print_debug("breakpoint added, id = " + str(breakpoint.id))
                         new_breakpoints.append(breakpoint.id)
-        except BaseException: # explicitly catch ctrl+c/sysexit
+        except BaseException:  # explicitly catch ctrl+c/sysexit
             print_debug("breakpoint listener shutting down")
 
     # Start the listener and let it run as a daemon
@@ -133,7 +147,9 @@ def start_breakpoint_listener(target):
     listener_thread.start()
 
     # Register the listener with the target
-    target.GetBroadcaster().AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged)
+    target.GetBroadcaster().AddListener(
+        listener, lldb.SBTarget.eBroadcastBitBreakpointChanged
+    )
 
 
 def start_watchdog():
@@ -159,6 +175,7 @@ def start_watchdog():
     watchdog_thread.daemon = True
     watchdog_thread.start()
 
+
 ####################################################################################################
 # ~main
 ####################################################################################################
@@ -193,8 +210,14 @@ target_error = lldb.SBError()
 target = debugger.CreateTarget(target_path, None, None, True, target_error)
 
 if not target:
-    print("Could not create debugging target '" + target_path + "': " +
-          str(target_error) + ". Aborting.", file=sys.stderr)
+    print(
+        "Could not create debugging target '"
+        + target_path
+        + "': "
+        + str(target_error)
+        + ". Aborting.",
+        file=sys.stderr,
+    )
     sys.exit(1)
 
 
@@ -204,15 +227,19 @@ start_breakpoint_listener(target)
 command_interpreter = debugger.GetCommandInterpreter()
 
 try:
-    script_file = open(script_path, 'r')
+    script_file = open(script_path, "r")
 
     for line in script_file:
         command = line.strip()
-        if command == "run" or command == "r" or re.match("^process\s+launch.*", command):
+        if (
+            command == "run"
+            or command == "r"
+            or re.match("^process\s+launch.*", command)
+        ):
             # Before starting to run the program, let the thread sleep a bit, so all
             # breakpoint added events can be processed
             time.sleep(0.5)
-        if command != '':
+        if command != "":
             execute_command(command_interpreter, command)
 
 except IOError as e:
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands
index 4be2dba34f6..ef0c3740f03 100644
--- a/src/etc/lldb_commands
+++ b/src/etc/lldb_commands
@@ -1,4 +1,25 @@
-type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)String$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?str$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?\\[.+\\]$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::([a-z_]+::)+)PathBuf$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
+type synthetic add -l lldb_lookup.synthetic_lookup -x "^(.*)$" --category Rust
+type summary add -F _ -e -x -h "^.*$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?str$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index a42ce111ebc..c24ec8ab310 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -1,7 +1,12 @@
 import sys
 
-from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
-    eBasicTypeUnsignedChar
+from lldb import (
+    SBData,
+    SBError,
+    eBasicTypeLong,
+    eBasicTypeUnsignedLong,
+    eBasicTypeUnsignedChar,
+)
 
 # from lldb.formatters import Logger
 
@@ -50,13 +55,17 @@ class ValueBuilder:
     def from_int(self, name, value):
         # type: (str, int) -> SBValue
         type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
-        data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value])
+        data = SBData.CreateDataFromSInt64Array(
+            self.endianness, self.pointer_size, [value]
+        )
         return self.valobj.CreateValueFromData(name, data, type)
 
     def from_uint(self, name, value):
         # type: (str, int) -> SBValue
         type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
-        data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value])
+        data = SBData.CreateDataFromUInt64Array(
+            self.endianness, self.pointer_size, [value]
+        )
         return self.valobj.CreateValueFromData(name, data, type)
 
 
@@ -127,13 +136,17 @@ class EmptySyntheticProvider:
 
 def SizeSummaryProvider(valobj, dict):
     # type: (SBValue, dict) -> str
-    return 'size=' + str(valobj.GetNumChildren())
+    return "size=" + str(valobj.GetNumChildren())
 
 
 def vec_to_string(vec):
     length = vec.GetNumChildren()
     chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]
-    return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars)
+    return (
+        bytes(chars).decode(errors="replace")
+        if PY3
+        else "".join(chr(char) for char in chars)
+    )
 
 
 def StdStringSummaryProvider(valobj, dict):
@@ -172,7 +185,7 @@ def StdStrSummaryProvider(valobj, dict):
     error = SBError()
     process = data_ptr.GetProcess()
     data = process.ReadMemory(start, length, error)
-    data = data.decode(encoding='UTF-8') if PY3 else data
+    data = data.decode(encoding="UTF-8") if PY3 else data
     return '"%s"' % data
 
 
@@ -199,9 +212,9 @@ def StdPathSummaryProvider(valobj, dict):
     data = process.ReadMemory(start, length, error)
     if PY3:
         try:
-            data = data.decode(encoding='UTF-8')
+            data = data.decode(encoding="UTF-8")
         except UnicodeDecodeError:
-            return '%r' % data
+            return "%r" % data
     return '"%s"' % data
 
 
@@ -250,8 +263,10 @@ class StructSyntheticProvider:
         # type: () -> bool
         return True
 
+
 class ClangEncodedEnumProvider:
     """Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
+
     DISCRIMINANT_MEMBER_NAME = "$discr$"
     VALUE_MEMBER_NAME = "value"
 
@@ -260,7 +275,7 @@ class ClangEncodedEnumProvider:
         self.update()
 
     def has_children(self):
-       return True
+        return True
 
     def num_children(self):
         if self.is_default:
@@ -276,25 +291,32 @@ class ClangEncodedEnumProvider:
 
     def get_child_at_index(self, index):
         if index == 0:
-            return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME)
+            return self.variant.GetChildMemberWithName(
+                ClangEncodedEnumProvider.VALUE_MEMBER_NAME
+            )
         if index == 1:
             return self.variant.GetChildMemberWithName(
-                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
-
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
+            )
 
     def update(self):
         all_variants = self.valobj.GetChildAtIndex(0)
         index = self._getCurrentVariantIndex(all_variants)
         self.variant = all_variants.GetChildAtIndex(index)
-        self.is_default = self.variant.GetIndexOfChildWithName(
-            ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1
+        self.is_default = (
+            self.variant.GetIndexOfChildWithName(
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
+            )
+            == -1
+        )
 
     def _getCurrentVariantIndex(self, all_variants):
         default_index = 0
         for i in range(all_variants.GetNumChildren()):
             variant = all_variants.GetChildAtIndex(i)
             discr = variant.GetChildMemberWithName(
-                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
+            )
             if discr.IsValid():
                 discr_unsigned_value = discr.GetValueAsUnsigned()
                 if variant.GetName() == f"$variant${discr_unsigned_value}":
@@ -303,6 +325,7 @@ class ClangEncodedEnumProvider:
                 default_index = i
         return default_index
 
+
 class TupleSyntheticProvider:
     """Pretty-printer for tuples and tuple enum variants"""
 
@@ -336,7 +359,9 @@ class TupleSyntheticProvider:
         else:
             field = self.type.GetFieldAtIndex(index)
         element = self.valobj.GetChildMemberWithName(field.name)
-        return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType())
+        return self.valobj.CreateValueFromData(
+            str(index), element.GetData(), element.GetType()
+        )
 
     def update(self):
         # type: () -> None
@@ -373,7 +398,7 @@ class StdVecSyntheticProvider:
 
     def get_child_index(self, name):
         # type: (str) -> int
-        index = name.lstrip('[').rstrip(']')
+        index = name.lstrip("[").rstrip("]")
         if index.isdigit():
             return int(index)
         else:
@@ -383,15 +408,21 @@ class StdVecSyntheticProvider:
         # type: (int) -> SBValue
         start = self.data_ptr.GetValueAsUnsigned()
         address = start + index * self.element_type_size
-        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        element = self.data_ptr.CreateValueFromAddress(
+            "[%s]" % index, address, self.element_type
+        )
         return element
 
     def update(self):
         # type: () -> None
         self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
-        self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
+        self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
+            "inner"
+        )
 
-        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
+        self.data_ptr = unwrap_unique_or_non_null(
+            self.buf.GetChildMemberWithName("ptr")
+        )
 
         self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
         self.element_type_size = self.element_type.GetByteSize()
@@ -412,7 +443,7 @@ class StdSliceSyntheticProvider:
 
     def get_child_index(self, name):
         # type: (str) -> int
-        index = name.lstrip('[').rstrip(']')
+        index = name.lstrip("[").rstrip("]")
         if index.isdigit():
             return int(index)
         else:
@@ -422,7 +453,9 @@ class StdSliceSyntheticProvider:
         # type: (int) -> SBValue
         start = self.data_ptr.GetValueAsUnsigned()
         address = start + index * self.element_type_size
-        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        element = self.data_ptr.CreateValueFromAddress(
+            "[%s]" % index, address, self.element_type
+        )
         return element
 
     def update(self):
@@ -457,7 +490,7 @@ class StdVecDequeSyntheticProvider:
 
     def get_child_index(self, name):
         # type: (str) -> int
-        index = name.lstrip('[').rstrip(']')
+        index = name.lstrip("[").rstrip("]")
         if index.isdigit() and int(index) < self.size:
             return int(index)
         else:
@@ -467,20 +500,26 @@ class StdVecDequeSyntheticProvider:
         # type: (int) -> SBValue
         start = self.data_ptr.GetValueAsUnsigned()
         address = start + ((index + self.head) % self.cap) * self.element_type_size
-        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        element = self.data_ptr.CreateValueFromAddress(
+            "[%s]" % index, address, self.element_type
+        )
         return element
 
     def update(self):
         # type: () -> None
         self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
         self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
-        self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
+        self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
+            "inner"
+        )
         cap = self.buf.GetChildMemberWithName("cap")
         if cap.GetType().num_fields == 1:
             cap = cap.GetChildAtIndex(0)
         self.cap = cap.GetValueAsUnsigned()
 
-        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
+        self.data_ptr = unwrap_unique_or_non_null(
+            self.buf.GetChildMemberWithName("ptr")
+        )
 
         self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
         self.element_type_size = self.element_type.GetByteSize()
@@ -510,7 +549,7 @@ class StdOldHashMapSyntheticProvider:
 
     def get_child_index(self, name):
         # type: (str) -> int
-        index = name.lstrip('[').rstrip(']')
+        index = name.lstrip("[").rstrip("]")
         if index.isdigit():
             return int(index)
         else:
@@ -525,8 +564,14 @@ class StdOldHashMapSyntheticProvider:
         hashes = self.hash_uint_size * self.capacity
         align = self.pair_type_size
         # See `libcore/alloc.rs:padding_needed_for`
-        len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
-                (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
+        len_rounded_up = (
+            (
+                (((hashes + align) % self.modulo - 1) % self.modulo)
+                & ~((align - 1) % self.modulo)
+            )
+            % self.modulo
+            - hashes
+        ) % self.modulo
         # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes
 
         pairs_offset = hashes + len_rounded_up
@@ -535,12 +580,16 @@ class StdOldHashMapSyntheticProvider:
         table_index = self.valid_indices[index]
         idx = table_index & self.capacity_mask
         address = pairs_start + idx * self.pair_type_size
-        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
+        element = self.data_ptr.CreateValueFromAddress(
+            "[%s]" % index, address, self.pair_type
+        )
         if self.show_values:
             return element
         else:
             key = element.GetChildAtIndex(0)
-            return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
+            return self.valobj.CreateValueFromData(
+                "[%s]" % index, key.GetData(), key.GetType()
+            )
 
     def update(self):
         # type: () -> None
@@ -551,10 +600,12 @@ class StdOldHashMapSyntheticProvider:
         self.hashes = self.table.GetChildMemberWithName("hashes")
         self.hash_uint_type = self.hashes.GetType()
         self.hash_uint_size = self.hashes.GetType().GetByteSize()
-        self.modulo = 2 ** self.hash_uint_size
+        self.modulo = 2**self.hash_uint_size
         self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0)
 
-        self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned()
+        self.capacity_mask = self.table.GetChildMemberWithName(
+            "capacity_mask"
+        ).GetValueAsUnsigned()
         self.capacity = (self.capacity_mask + 1) % self.modulo
 
         marker = self.table.GetChildMemberWithName("marker").GetType()  # type: SBType
@@ -564,8 +615,9 @@ class StdOldHashMapSyntheticProvider:
         self.valid_indices = []
         for idx in range(self.capacity):
             address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size
-            hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address,
-                                                             self.hash_uint_type)
+            hash_uint = self.data_ptr.CreateValueFromAddress(
+                "[%s]" % idx, address, self.hash_uint_type
+            )
             hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)
             if hash_ptr.GetValueAsUnsigned() != 0:
                 self.valid_indices.append(idx)
@@ -592,7 +644,7 @@ class StdHashMapSyntheticProvider:
 
     def get_child_index(self, name):
         # type: (str) -> int
-        index = name.lstrip('[').rstrip(']')
+        index = name.lstrip("[").rstrip("]")
         if index.isdigit():
             return int(index)
         else:
@@ -605,19 +657,25 @@ class StdHashMapSyntheticProvider:
         if self.new_layout:
             idx = -(idx + 1)
         address = pairs_start + idx * self.pair_type_size
-        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
+        element = self.data_ptr.CreateValueFromAddress(
+            "[%s]" % index, address, self.pair_type
+        )
         if self.show_values:
             return element
         else:
             key = element.GetChildAtIndex(0)
-            return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
+            return self.valobj.CreateValueFromData(
+                "[%s]" % index, key.GetData(), key.GetType()
+            )
 
     def update(self):
         # type: () -> None
         table = self.table()
         inner_table = table.GetChildMemberWithName("table")
 
-        capacity = inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
+        capacity = (
+            inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
+        )
         ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
 
         self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned()
@@ -630,16 +688,21 @@ class StdHashMapSyntheticProvider:
         if self.new_layout:
             self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType())
         else:
-            self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(0)
+            self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(
+                0
+            )
 
         u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)
-        u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
+        u8_type_size = (
+            self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
+        )
 
         self.valid_indices = []
         for idx in range(capacity):
             address = ctrl.GetValueAsUnsigned() + idx * u8_type_size
-            value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address,
-                                                u8_type).GetValueAsUnsigned()
+            value = ctrl.CreateValueFromAddress(
+                "ctrl[%s]" % idx, address, u8_type
+            ).GetValueAsUnsigned()
             is_present = value & 128 == 0
             if is_present:
                 self.valid_indices.append(idx)
@@ -691,10 +754,16 @@ class StdRcSyntheticProvider:
 
         self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
 
-        self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(
-            0).GetChildMemberWithName("value")
-        self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(
-            0).GetChildMemberWithName("value")
+        self.strong = (
+            self.ptr.GetChildMemberWithName("strong")
+            .GetChildAtIndex(0)
+            .GetChildMemberWithName("value")
+        )
+        self.weak = (
+            self.ptr.GetChildMemberWithName("weak")
+            .GetChildAtIndex(0)
+            .GetChildMemberWithName("value")
+        )
 
         self.value_builder = ValueBuilder(valobj)
 
@@ -772,7 +841,9 @@ class StdCellSyntheticProvider:
 def StdRefSummaryProvider(valobj, dict):
     # type: (SBValue, dict) -> str
     borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()
-    return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
+    return (
+        "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
+    )
 
 
 class StdRefSyntheticProvider:
@@ -785,11 +856,16 @@ class StdRefSyntheticProvider:
         borrow = valobj.GetChildMemberWithName("borrow")
         value = valobj.GetChildMemberWithName("value")
         if is_cell:
-            self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value")
+            self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName(
+                "value"
+            )
             self.value = value.GetChildMemberWithName("value")
         else:
-            self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName(
-                "value").GetChildMemberWithName("value")
+            self.borrow = (
+                borrow.GetChildMemberWithName("borrow")
+                .GetChildMemberWithName("value")
+                .GetChildMemberWithName("value")
+            )
             self.value = value.Dereference()
 
         self.value_builder = ValueBuilder(valobj)
@@ -832,7 +908,7 @@ def StdNonZeroNumberSummaryProvider(valobj, _dict):
 
     # FIXME: Avoid printing as character literal,
     #        see https://github.com/llvm/llvm-project/issues/65076.
-    if inner_inner.GetTypeName() in ['char', 'unsigned char']:
-      return str(inner_inner.GetValueAsSigned())
+    if inner_inner.GetTypeName() in ["char", "unsigned char"]:
+        return str(inner_inner.GetValueAsSigned())
     else:
-      return inner_inner.GetValue()
+        return inner_inner.GetValue()
diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json
index d1b186fd316..b104356d44c 100644
--- a/src/etc/rust_analyzer_settings.json
+++ b/src/etc/rust_analyzer_settings.json
@@ -34,5 +34,8 @@
     "rust-analyzer.rustc.source": "./Cargo.toml",
     "rust-analyzer.cargo.extraEnv": {
         "RUSTC_BOOTSTRAP": "1"
+    },
+    "rust-analyzer.server.extraEnv": {
+        "RUSTUP_TOOLCHAIN": "nightly"
     }
 }
diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py
index 190fbc13a17..42ec9bed9bd 100644
--- a/src/etc/rust_types.py
+++ b/src/etc/rust_types.py
@@ -54,7 +54,7 @@ STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$")
 STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$")
 STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$")
 STD_PATHBUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$")
-STD_PATH_REGEX =  re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$")
+STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$")
 
 TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
 
@@ -84,6 +84,7 @@ STD_TYPE_TO_REGEX = {
     RustType.STD_PATH: STD_PATH_REGEX,
 }
 
+
 def is_tuple_fields(fields):
     # type: (list) -> bool
     return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields)
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 3fe567b1c39..185898c31b7 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
 use rustc_hir as hir;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::bug;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, Region, Ty};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{Symbol, kw};
@@ -182,7 +183,7 @@ fn clean_param_env<'tcx>(
                     .is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id()))
         })
         .map(|pred| {
-            tcx.fold_regions(pred, |r, _| match *r {
+            fold_regions(tcx, pred, |r, _| match *r {
                 // FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that
                 // we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds
                 // of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5b407ea9a2b..34141c47cf3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2647,7 +2647,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
             });
             args.tokens = TokenStream::new(tokens);
         }
-        ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {}
+        ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {}
     }
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 715bf68374a..cba947eb833 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1241,19 +1241,6 @@ impl Attributes {
     }
 }
 
-impl PartialEq for Attributes {
-    fn eq(&self, rhs: &Self) -> bool {
-        self.doc_strings == rhs.doc_strings
-            && self
-                .other_attrs
-                .iter()
-                .map(|attr| attr.id)
-                .eq(rhs.other_attrs.iter().map(|attr| attr.id))
-    }
-}
-
-impl Eq for Attributes {}
-
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) enum GenericBound {
     TraitBound(PolyTrait, hir::TraitBoundModifiers),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a562a9eee71..0dda3466a71 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -5,12 +5,12 @@ use std::{io, mem};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unord::UnordSet;
+use rustc_errors::TerminalUrl;
 use rustc_errors::codes::*;
 use rustc_errors::emitter::{
     DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination,
 };
 use rustc_errors::json::JsonEmitter;
-use rustc_errors::{ErrorGuaranteed, TerminalUrl};
 use rustc_feature::UnstableFeatures;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
@@ -326,7 +326,7 @@ pub(crate) fn run_global_ctxt(
     show_coverage: bool,
     render_options: RenderOptions,
     output_format: OutputFormat,
-) -> Result<(clean::Crate, RenderOptions, Cache), ErrorGuaranteed> {
+) -> (clean::Crate, RenderOptions, Cache) {
     // Certain queries assume that some checks were run elsewhere
     // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
     // so type-check everything other than function bodies in this crate before running lints.
@@ -340,9 +340,7 @@ pub(crate) fn run_global_ctxt(
         tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
     });
 
-    if let Some(guar) = tcx.dcx().has_errors() {
-        return Err(guar);
-    }
+    tcx.dcx().abort_if_errors();
 
     tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
     tcx.sess.time("check_mod_attrs", || {
@@ -446,11 +444,9 @@ pub(crate) fn run_global_ctxt(
         LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous };
     collector.resolve_ambiguities();
 
-    if let Some(guar) = tcx.dcx().has_errors() {
-        return Err(guar);
-    }
+    tcx.dcx().abort_if_errors();
 
-    Ok((krate, ctxt.render_options, ctxt.cache))
+    (krate, ctxt.render_options, ctxt.cache)
 }
 
 /// Due to <https://github.com/rust-lang/rust/pull/73566>,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index da1316a19cc..70d9269ae5c 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -16,7 +16,7 @@ pub(crate) use markdown::test as test_markdown;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError};
+use rustc_errors::{ColorConfig, DiagCtxtHandle};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::interface;
@@ -89,11 +89,7 @@ fn get_doctest_dir() -> io::Result<TempDir> {
     TempFileBuilder::new().prefix("rustdoctest").tempdir()
 }
 
-pub(crate) fn run(
-    dcx: DiagCtxtHandle<'_>,
-    input: Input,
-    options: RustdocOptions,
-) -> Result<(), ErrorGuaranteed> {
+pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions) {
     let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
 
     // See core::create_config for what's going on here.
@@ -167,7 +163,7 @@ pub(crate) fn run(
         Err(error) => return crate::wrap_return(dcx, Err(error)),
     };
     let args_path = temp_dir.path().join("rustdoc-cfgs");
-    crate::wrap_return(dcx, generate_args_file(&args_path, &options))?;
+    crate::wrap_return(dcx, generate_args_file(&args_path, &options));
 
     let CreateRunnableDocTests {
         standalone_tests,
@@ -179,7 +175,7 @@ pub(crate) fn run(
         ..
     } = interface::run_compiler(config, |compiler| {
         compiler.enter(|queries| {
-            let collector = queries.global_ctxt()?.enter(|tcx| {
+            let collector = queries.global_ctxt().enter(|tcx| {
                 let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
                 let opts = scrape_test_config(crate_name, crate_attrs, args_path);
@@ -196,13 +192,11 @@ pub(crate) fn run(
 
                 collector
             });
-            if compiler.sess.dcx().has_errors().is_some() {
-                FatalError.raise();
-            }
+            compiler.sess.dcx().abort_if_errors();
 
-            Ok(collector)
+            collector
         })
-    })?;
+    });
 
     run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests);
 
@@ -246,8 +240,6 @@ pub(crate) fn run(
             eprintln!("{unused_extern_json}");
         }
     }
-
-    Ok(())
 }
 
 pub(crate) fn run_tests(
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index edd7d56b179..5e4e6f27a15 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -1,5 +1,5 @@
+use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_middle::ty::TyCtxt;
-use tracing::debug;
 
 use crate::clean;
 use crate::config::RenderOptions;
@@ -18,6 +18,19 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     /// This is true for html, and false for json. See #80664
     const RUN_ON_MODULE: bool;
 
+    /// This associated type is the type where the current module information is stored.
+    ///
+    /// For each module, we go through their items by calling for each item:
+    ///
+    /// 1. `save_module_data`
+    /// 2. `item`
+    /// 3. `restore_module_data`
+    ///
+    /// This is because the `item` method might update information in `self` (for example if the child
+    /// is a module). To prevent it from impacting the other children of the current module, we need to
+    /// reset the information between each call to `item` by using `restore_module_data`.
+    type ModuleData;
+
     /// Sets up any state required for the renderer. When this is called the cache has already been
     /// populated.
     fn init(
@@ -27,8 +40,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
         tcx: TyCtxt<'tcx>,
     ) -> Result<(Self, clean::Crate), Error>;
 
-    /// Make a new renderer to render a child of the item currently being rendered.
-    fn make_child_renderer(&self) -> Self;
+    /// This method is called right before call [`Self::item`]. This method returns a type
+    /// containing information that needs to be reset after the [`Self::item`] method has been
+    /// called with the [`Self::restore_module_data`] method.
+    ///
+    /// In short it goes like this:
+    ///
+    /// ```ignore (not valid code)
+    /// let reset_data = renderer.save_module_data();
+    /// renderer.item(item)?;
+    /// renderer.restore_module_data(reset_data);
+    /// ```
+    fn save_module_data(&mut self) -> Self::ModuleData;
+    /// Used to reset current module's information.
+    fn restore_module_data(&mut self, info: Self::ModuleData);
 
     /// Renders a single non-module item. This means no recursive sub-item rendering is required.
     fn item(&mut self, item: clean::Item) -> Result<(), Error>;
@@ -47,6 +72,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     fn cache(&self) -> &Cache;
 }
 
+fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
+    cx: &mut T,
+    item: clean::Item,
+    prof: &SelfProfilerRef,
+) -> Result<(), Error> {
+    if item.is_mod() && T::RUN_ON_MODULE {
+        // modules are special because they add a namespace. We also need to
+        // recurse into the items of the module as well.
+        let _timer =
+            prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
+
+        cx.mod_item_in(&item)?;
+        let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
+            item.inner.kind
+        else {
+            unreachable!()
+        };
+        for it in module.items {
+            let info = cx.save_module_data();
+            run_format_inner(cx, it, prof)?;
+            cx.restore_module_data(info);
+        }
+
+        cx.mod_item_out()?;
+    // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
+    // cases. Use an explicit match instead.
+    } else if let Some(item_name) = item.name
+        && !item.is_extern_crate()
+    {
+        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
+    }
+    Ok(())
+}
+
 /// Main method for rendering a crate.
 pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
     krate: clean::Crate,
@@ -66,36 +125,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
     }
 
     // Render the crate documentation
-    let mut work = vec![(format_renderer.make_child_renderer(), krate.module)];
-
-    while let Some((mut cx, item)) = work.pop() {
-        if item.is_mod() && T::RUN_ON_MODULE {
-            // modules are special because they add a namespace. We also need to
-            // recurse into the items of the module as well.
-            let _timer =
-                prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
-
-            cx.mod_item_in(&item)?;
-            let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
-                item.inner.kind
-            else {
-                unreachable!()
-            };
-            for it in module.items {
-                debug!("Adding {:?} to worklist", it.name);
-                work.push((cx.make_child_renderer(), it));
-            }
-
-            cx.mod_item_out()?;
-        // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
-        // cases. Use an explicit match instead.
-        } else if let Some(item_name) = item.name
-            && !item.is_extern_crate()
-        {
-            prof.generic_activity_with_arg("render_item", item_name.as_str())
-                .run(|| cx.item(item))?;
-        }
-    }
+    run_format_inner(&mut format_renderer, krate.module, prof)?;
+
     prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
         .run(|| format_renderer.after_krate())
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b6829d5457b..90c49270566 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -32,7 +32,8 @@ use std::iter::Peekable;
 use std::ops::{ControlFlow, Range};
 use std::path::PathBuf;
 use std::str::{self, CharIndices};
-use std::sync::OnceLock;
+use std::sync::atomic::AtomicUsize;
+use std::sync::{Arc, Weak};
 
 use pulldown_cmark::{
     BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
@@ -1302,8 +1303,20 @@ impl LangString {
     }
 }
 
-impl Markdown<'_> {
+impl<'a> Markdown<'a> {
     pub fn into_string(self) -> String {
+        // This is actually common enough to special-case
+        if self.content.is_empty() {
+            return String::new();
+        }
+
+        let mut s = String::with_capacity(self.content.len() * 3 / 2);
+        html::push_html(&mut s, self.into_iter());
+
+        s
+    }
+
+    fn into_iter(self) -> CodeBlocks<'a, 'a, impl Iterator<Item = Event<'a>>> {
         let Markdown {
             content: md,
             links,
@@ -1314,32 +1327,72 @@ impl Markdown<'_> {
             heading_offset,
         } = self;
 
-        // This is actually common enough to special-case
-        if md.is_empty() {
-            return String::new();
-        }
-        let mut replacer = |broken_link: BrokenLink<'_>| {
+        let replacer = move |broken_link: BrokenLink<'_>| {
             links
                 .iter()
                 .find(|link| *link.original_text == *broken_link.reference)
                 .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
         };
 
-        let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
+        let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(replacer));
         let p = p.into_offset_iter();
 
-        let mut s = String::with_capacity(md.len() * 3 / 2);
-
         ids.handle_footnotes(|ids, existing_footnotes| {
             let p = HeadingLinks::new(p, None, ids, heading_offset);
             let p = footnotes::Footnotes::new(p, existing_footnotes);
             let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
             let p = TableWrapper::new(p);
-            let p = CodeBlocks::new(p, codes, edition, playground);
-            html::push_html(&mut s, p);
-        });
+            CodeBlocks::new(p, codes, edition, playground)
+        })
+    }
 
-        s
+    /// Convert markdown to (summary, remaining) HTML.
+    ///
+    /// - The summary is the first top-level Markdown element (usually a paragraph, but potentially
+    ///   any block).
+    /// - The remaining docs contain everything after the summary.
+    pub(crate) fn split_summary_and_content(self) -> (Option<String>, Option<String>) {
+        if self.content.is_empty() {
+            return (None, None);
+        }
+        let mut p = self.into_iter();
+
+        let mut event_level = 0;
+        let mut summary_events = Vec::new();
+        let mut get_next_tag = false;
+
+        let mut end_of_summary = false;
+        while let Some(event) = p.next() {
+            match event {
+                Event::Start(_) => event_level += 1,
+                Event::End(kind) => {
+                    event_level -= 1;
+                    if event_level == 0 {
+                        // We're back at the "top" so it means we're done with the summary.
+                        end_of_summary = true;
+                        // We surround tables with `<div>` HTML tags so this is a special case.
+                        get_next_tag = kind == TagEnd::Table;
+                    }
+                }
+                _ => {}
+            }
+            summary_events.push(event);
+            if end_of_summary {
+                if get_next_tag && let Some(event) = p.next() {
+                    summary_events.push(event);
+                }
+                break;
+            }
+        }
+        let mut summary = String::new();
+        html::push_html(&mut summary, summary_events.into_iter());
+        if summary.is_empty() {
+            return (None, None);
+        }
+        let mut content = String::new();
+        html::push_html(&mut content, p);
+
+        if content.is_empty() { (Some(summary), None) } else { (Some(summary), Some(content)) }
     }
 }
 
@@ -1882,75 +1935,82 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
 
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
-    map: FxHashMap<Cow<'static, str>, usize>,
-    existing_footnotes: usize,
-}
-
-// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
-static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new();
-
-fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
-    let mut map = FxHashMap::default();
-    // This is the list of IDs used in JavaScript.
-    map.insert("help".into(), 1);
-    map.insert("settings".into(), 1);
-    map.insert("not-displayed".into(), 1);
-    map.insert("alternative-display".into(), 1);
-    map.insert("search".into(), 1);
-    map.insert("crate-search".into(), 1);
-    map.insert("crate-search-div".into(), 1);
-    // This is the list of IDs used in HTML generated in Rust (including the ones
-    // used in tera template files).
-    map.insert("themeStyle".into(), 1);
-    map.insert("settings-menu".into(), 1);
-    map.insert("help-button".into(), 1);
-    map.insert("sidebar-button".into(), 1);
-    map.insert("main-content".into(), 1);
-    map.insert("toggle-all-docs".into(), 1);
-    map.insert("all-types".into(), 1);
-    map.insert("default-settings".into(), 1);
-    map.insert("sidebar-vars".into(), 1);
-    map.insert("copy-path".into(), 1);
-    map.insert("rustdoc-toc".into(), 1);
-    map.insert("rustdoc-modnav".into(), 1);
-    // This is the list of IDs used by rustdoc sections (but still generated by
-    // rustdoc).
-    map.insert("fields".into(), 1);
-    map.insert("variants".into(), 1);
-    map.insert("implementors-list".into(), 1);
-    map.insert("synthetic-implementors-list".into(), 1);
-    map.insert("foreign-impls".into(), 1);
-    map.insert("implementations".into(), 1);
-    map.insert("trait-implementations".into(), 1);
-    map.insert("synthetic-implementations".into(), 1);
-    map.insert("blanket-implementations".into(), 1);
-    map.insert("required-associated-types".into(), 1);
-    map.insert("provided-associated-types".into(), 1);
-    map.insert("provided-associated-consts".into(), 1);
-    map.insert("required-associated-consts".into(), 1);
-    map.insert("required-methods".into(), 1);
-    map.insert("provided-methods".into(), 1);
-    map.insert("dyn-compatibility".into(), 1);
-    map.insert("implementors".into(), 1);
-    map.insert("synthetic-implementors".into(), 1);
-    map.insert("implementations-list".into(), 1);
-    map.insert("trait-implementations-list".into(), 1);
-    map.insert("synthetic-implementations-list".into(), 1);
-    map.insert("blanket-implementations-list".into(), 1);
-    map.insert("deref-methods".into(), 1);
-    map.insert("layout".into(), 1);
-    map.insert("aliased-type".into(), 1);
-    map
+    map: FxHashMap<String, usize>,
+    existing_footnotes: Arc<AtomicUsize>,
+}
+
+fn is_default_id(id: &str) -> bool {
+    matches!(
+        id,
+        // This is the list of IDs used in JavaScript.
+        "help"
+        | "settings"
+        | "not-displayed"
+        | "alternative-display"
+        | "search"
+        | "crate-search"
+        | "crate-search-div"
+        // This is the list of IDs used in HTML generated in Rust (including the ones
+        // used in tera template files).
+        | "themeStyle"
+        | "settings-menu"
+        | "help-button"
+        | "sidebar-button"
+        | "main-content"
+        | "toggle-all-docs"
+        | "all-types"
+        | "default-settings"
+        | "sidebar-vars"
+        | "copy-path"
+        | "rustdoc-toc"
+        | "rustdoc-modnav"
+        // This is the list of IDs used by rustdoc sections (but still generated by
+        // rustdoc).
+        | "fields"
+        | "variants"
+        | "implementors-list"
+        | "synthetic-implementors-list"
+        | "foreign-impls"
+        | "implementations"
+        | "trait-implementations"
+        | "synthetic-implementations"
+        | "blanket-implementations"
+        | "required-associated-types"
+        | "provided-associated-types"
+        | "provided-associated-consts"
+        | "required-associated-consts"
+        | "required-methods"
+        | "provided-methods"
+        | "dyn-compatibility"
+        | "implementors"
+        | "synthetic-implementors"
+        | "implementations-list"
+        | "trait-implementations-list"
+        | "synthetic-implementations-list"
+        | "blanket-implementations-list"
+        | "deref-methods"
+        | "layout"
+        | "aliased-type"
+    )
 }
 
 impl IdMap {
     pub fn new() -> Self {
-        IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
+        IdMap { map: FxHashMap::default(), existing_footnotes: Arc::new(AtomicUsize::new(0)) }
     }
 
     pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
         let id = match self.map.get_mut(candidate.as_ref()) {
-            None => candidate.to_string(),
+            None => {
+                let candidate = candidate.to_string();
+                if is_default_id(&candidate) {
+                    let id = format!("{}-{}", candidate, 1);
+                    self.map.insert(candidate.into(), 2);
+                    id
+                } else {
+                    candidate
+                }
+            }
             Some(a) => {
                 let id = format!("{}-{}", candidate.as_ref(), *a);
                 *a += 1;
@@ -1964,10 +2024,17 @@ impl IdMap {
 
     /// Method to handle `existing_footnotes` increment automatically (to prevent forgetting
     /// about it).
-    pub(crate) fn handle_footnotes<F: FnOnce(&mut Self, &mut usize)>(&mut self, closure: F) {
-        let mut existing_footnotes = self.existing_footnotes;
+    pub(crate) fn handle_footnotes<'a, T, F: FnOnce(&'a mut Self, Weak<AtomicUsize>) -> T>(
+        &'a mut self,
+        closure: F,
+    ) -> T {
+        let existing_footnotes = Arc::downgrade(&self.existing_footnotes);
+
+        closure(self, existing_footnotes)
+    }
 
-        closure(self, &mut existing_footnotes);
-        self.existing_footnotes = existing_footnotes;
+    pub(crate) fn clear(&mut self) {
+        self.map.clear();
+        self.existing_footnotes = Arc::new(AtomicUsize::new(0));
     }
 }
diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs
index ebf55b38373..519778e4d3b 100644
--- a/src/librustdoc/html/markdown/footnotes.rs
+++ b/src/librustdoc/html/markdown/footnotes.rs
@@ -1,5 +1,8 @@
 //! Markdown footnote handling.
+
 use std::fmt::Write as _;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Weak};
 
 use pulldown_cmark::{CowStr, Event, Tag, TagEnd, html};
 use rustc_data_structures::fx::FxIndexMap;
@@ -8,10 +11,11 @@ use super::SpannedEvent;
 
 /// Moves all footnote definitions to the end and add back links to the
 /// references.
-pub(super) struct Footnotes<'a, 'b, I> {
+pub(super) struct Footnotes<'a, I> {
     inner: I,
     footnotes: FxIndexMap<String, FootnoteDef<'a>>,
-    existing_footnotes: &'b mut usize,
+    existing_footnotes: Arc<AtomicUsize>,
+    start_id: usize,
 }
 
 /// The definition of a single footnote.
@@ -21,13 +25,16 @@ struct FootnoteDef<'a> {
     id: usize,
 }
 
-impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
-    pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self {
-        Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes }
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> {
+    pub(super) fn new(iter: I, existing_footnotes: Weak<AtomicUsize>) -> Self {
+        let existing_footnotes =
+            existing_footnotes.upgrade().expect("`existing_footnotes` was dropped");
+        let start_id = existing_footnotes.load(Ordering::Relaxed);
+        Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id }
     }
 
     fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) {
-        let new_id = self.footnotes.len() + 1 + *self.existing_footnotes;
+        let new_id = self.footnotes.len() + 1 + self.start_id;
         let key = key.to_owned();
         let FootnoteDef { content, id } =
             self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
@@ -44,7 +51,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
             id,
             // Although the ID count is for the whole page, the footnote reference
             // are local to the item so we make this ID "local" when displayed.
-            id - *self.existing_footnotes
+            id - self.start_id
         );
         Event::Html(reference.into())
     }
@@ -64,7 +71,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
     }
 }
 
-impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I> {
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
     type Item = SpannedEvent<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -87,7 +94,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I>
                         // After all the markdown is emmited, emit an <hr> then all the footnotes
                         // in a list.
                         let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
-                        *self.existing_footnotes += defs.len();
+                        self.existing_footnotes.fetch_add(defs.len(), Ordering::Relaxed);
                         let defs_html = render_footnotes_defs(defs);
                         return Some((Event::Html(defs_html.into()), 0..0));
                     } else {
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 3a814462174..2d5df75e7dc 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -2,7 +2,6 @@ use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::rc::Rc;
 use std::sync::mpsc::{Receiver, channel};
 
 use rinja::Template;
@@ -49,36 +48,49 @@ pub(crate) struct Context<'tcx> {
     /// The current destination folder of where HTML artifacts should be placed.
     /// This changes as the context descends into the module hierarchy.
     pub(crate) dst: PathBuf,
-    /// A flag, which when `true`, will render pages which redirect to the
-    /// real location of an item. This is used to allow external links to
-    /// publicly reused items to redirect to the right location.
-    pub(super) render_redirect_pages: bool,
     /// Tracks section IDs for `Deref` targets so they match in both the main
     /// body and the sidebar.
-    pub(super) deref_id_map: DefIdMap<String>,
+    pub(super) deref_id_map: RefCell<DefIdMap<String>>,
     /// The map used to ensure all generated 'id=' attributes are unique.
-    pub(super) id_map: IdMap,
+    pub(super) id_map: RefCell<IdMap>,
     /// Shared mutable state.
     ///
     /// Issue for improving the situation: [#82381][]
     ///
     /// [#82381]: https://github.com/rust-lang/rust/issues/82381
-    pub(crate) shared: Rc<SharedContext<'tcx>>,
+    pub(crate) shared: SharedContext<'tcx>,
+    /// Collection of all types with notable traits referenced in the current module.
+    pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>,
+    /// Contains information that needs to be saved and reset after rendering an item which is
+    /// not a module.
+    pub(crate) info: ContextInfo,
+}
+
+/// This struct contains the information that needs to be reset between each
+/// [`FormatRenderer::item`] call.
+///
+/// When we enter a new module, we set these values for the whole module but they might be updated
+/// in each child item (especially if it's a module). So to prevent these changes to impact other
+/// items rendering in the same module, we need to reset them to the module's set values.
+#[derive(Clone, Copy)]
+pub(crate) struct ContextInfo {
+    /// A flag, which when `true`, will render pages which redirect to the
+    /// real location of an item. This is used to allow external links to
+    /// publicly reused items to redirect to the right location.
+    pub(super) render_redirect_pages: bool,
     /// This flag indicates whether source links should be generated or not. If
     /// the source files are present in the html rendering, then this will be
     /// `true`.
     pub(crate) include_sources: bool,
-    /// Collection of all types with notable traits referenced in the current module.
-    pub(crate) types_with_notable_traits: FxIndexSet<clean::Type>,
     /// Field used during rendering, to know if we're inside an inlined item.
     pub(crate) is_inside_inlined_module: bool,
 }
 
-// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
-#[cfg(all(not(windows), target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 192);
-#[cfg(all(windows, target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 200);
+impl ContextInfo {
+    fn new(include_sources: bool) -> Self {
+        Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false }
+    }
+}
 
 /// Shared mutable state used in [`Context`] and elsewhere.
 pub(crate) struct SharedContext<'tcx> {
@@ -163,8 +175,8 @@ impl<'tcx> Context<'tcx> {
         self.shared.tcx.sess
     }
 
-    pub(super) fn derive_id<S: AsRef<str> + ToString>(&mut self, id: S) -> String {
-        self.id_map.derive(id)
+    pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String {
+        self.id_map.borrow_mut().derive(id)
     }
 
     /// String representation of how to get back to the root path of the 'doc/'
@@ -174,14 +186,16 @@ impl<'tcx> Context<'tcx> {
     }
 
     fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
-        let mut render_redirect_pages = self.render_redirect_pages;
+        let mut render_redirect_pages = self.info.render_redirect_pages;
         // If the item is stripped but inlined, links won't point to the item so no need to generate
         // a file for it.
         if it.is_stripped()
             && let Some(def_id) = it.def_id()
             && def_id.is_local()
         {
-            if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
+            if self.info.is_inside_inlined_module
+                || self.shared.cache.inlined_items.contains(&def_id)
+            {
                 // For now we're forced to generate a redirect page for stripped items until
                 // `record_extern_fqn` correctly points to external items.
                 render_redirect_pages = true;
@@ -221,24 +235,23 @@ impl<'tcx> Context<'tcx> {
         };
 
         if !render_redirect_pages {
-            let clone_shared = Rc::clone(&self.shared);
+            let mut page_buffer = Buffer::html();
+            print_item(self, it, &mut page_buffer);
             let page = layout::Page {
                 css_class: tyname_s,
                 root_path: &self.root_path(),
-                static_root_path: clone_shared.static_root_path.as_deref(),
+                static_root_path: self.shared.static_root_path.as_deref(),
                 title: &title,
                 description: &desc,
-                resource_suffix: &clone_shared.resource_suffix,
+                resource_suffix: &self.shared.resource_suffix,
                 rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
             };
-            let mut page_buffer = Buffer::html();
-            print_item(self, it, &mut page_buffer);
             layout::render(
-                &clone_shared.layout,
+                &self.shared.layout,
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
                 move |buf: &mut Buffer| buf.push_buffer(page_buffer),
-                &clone_shared.style_files,
+                &self.shared.style_files,
             )
         } else {
             if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
@@ -441,6 +454,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
     }
 
     const RUN_ON_MODULE: bool = true;
+    type ModuleData = ContextInfo;
 
     fn init(
         krate: clean::Crate,
@@ -562,13 +576,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         let mut cx = Context {
             current: Vec::new(),
             dst,
-            render_redirect_pages: false,
-            id_map,
+            id_map: RefCell::new(id_map),
             deref_id_map: Default::default(),
-            shared: Rc::new(scx),
-            include_sources,
-            types_with_notable_traits: FxIndexSet::default(),
-            is_inside_inlined_module: false,
+            shared: scx,
+            types_with_notable_traits: RefCell::new(FxIndexSet::default()),
+            info: ContextInfo::new(include_sources),
         };
 
         if emit_crate {
@@ -582,18 +594,15 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         Ok((cx, krate))
     }
 
-    fn make_child_renderer(&self) -> Self {
-        Self {
-            current: self.current.clone(),
-            dst: self.dst.clone(),
-            render_redirect_pages: self.render_redirect_pages,
-            deref_id_map: Default::default(),
-            id_map: IdMap::new(),
-            shared: Rc::clone(&self.shared),
-            include_sources: self.include_sources,
-            types_with_notable_traits: FxIndexSet::default(),
-            is_inside_inlined_module: self.is_inside_inlined_module,
-        }
+    fn save_module_data(&mut self) -> Self::ModuleData {
+        self.deref_id_map.borrow_mut().clear();
+        self.id_map.borrow_mut().clear();
+        self.types_with_notable_traits.borrow_mut().clear();
+        self.info
+    }
+
+    fn restore_module_data(&mut self, info: Self::ModuleData) {
+        self.info = info;
     }
 
     fn after_krate(&mut self) -> Result<(), Error> {
@@ -607,7 +616,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !root_path.ends_with('/') {
             root_path.push('/');
         }
-        let shared = Rc::clone(&self.shared);
+        let shared = &self.shared;
         let mut page = layout::Page {
             title: "List of all items in this crate",
             css_class: "mod sys",
@@ -754,11 +763,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             shared.fs.write(redirect_map_path, paths)?;
         }
 
-        // No need for it anymore.
-        drop(shared);
-
         // Flush pending errors.
-        Rc::get_mut(&mut self.shared).unwrap().fs.close();
+        self.shared.fs.close();
         let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
         if nb_errors > 0 {
             Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
@@ -775,8 +781,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         // External crates will provide links to these structures, so
         // these modules are recursed into, but not rendered normally
         // (a flag on the context).
-        if !self.render_redirect_pages {
-            self.render_redirect_pages = item.is_stripped();
+        if !self.info.render_redirect_pages {
+            self.info.render_redirect_pages = item.is_stripped();
         }
         let item_name = item.name.unwrap();
         self.dst.push(item_name.as_str());
@@ -793,19 +799,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                 self.shared.fs.write(joint_dst, buf)?;
             }
         }
-        if !self.is_inside_inlined_module {
+        if !self.info.is_inside_inlined_module {
             if let Some(def_id) = item.def_id()
                 && self.cache().inlined_items.contains(&def_id)
             {
-                self.is_inside_inlined_module = true;
+                self.info.is_inside_inlined_module = true;
             }
         } else if !self.cache().document_hidden && item.is_doc_hidden() {
             // We're not inside an inlined module anymore since this one cannot be re-exported.
-            self.is_inside_inlined_module = false;
+            self.info.is_inside_inlined_module = false;
         }
 
         // Render sidebar-items.js used throughout this module.
-        if !self.render_redirect_pages {
+        if !self.info.render_redirect_pages {
             let (clean::StrippedItem(box clean::ModuleItem(ref module))
             | clean::ModuleItem(ref module)) = item.kind
             else {
@@ -836,8 +842,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         // External crates will provide links to these structures, so
         // these modules are recursed into, but not rendered normally
         // (a flag on the context).
-        if !self.render_redirect_pages {
-            self.render_redirect_pages = item.is_stripped();
+        if !self.info.render_redirect_pages {
+            self.info.render_redirect_pages = item.is_stripped();
         }
 
         let buf = self.render_item(&item, false);
@@ -850,7 +856,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             let joint_dst = self.dst.join(file_name);
             self.shared.fs.write(joint_dst, buf)?;
 
-            if !self.render_redirect_pages {
+            if !self.info.render_redirect_pages {
                 self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
             }
             // If the item is a macro, redirect from the old macro URL (with !)
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 7c5048cd164..e013829e5e0 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -41,7 +41,6 @@ use std::collections::VecDeque;
 use std::fmt::{self, Write};
 use std::iter::Peekable;
 use std::path::PathBuf;
-use std::rc::Rc;
 use std::{fs, str};
 
 use rinja::Template;
@@ -504,7 +503,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
 }
 
 fn document<'a, 'cx: 'a>(
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     item: &'a clean::Item,
     parent: Option<&'a clean::Item>,
     heading_offset: HeadingOffset,
@@ -525,7 +524,7 @@ fn document<'a, 'cx: 'a>(
 
 /// Render md_text as markdown.
 fn render_markdown<'a, 'cx: 'a>(
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     md_text: &'a str,
     links: Vec<RenderedLink>,
     heading_offset: HeadingOffset,
@@ -537,7 +536,7 @@ fn render_markdown<'a, 'cx: 'a>(
             Markdown {
                 content: md_text,
                 links: &links,
-                ids: &mut cx.id_map,
+                ids: &mut cx.id_map.borrow_mut(),
                 error_codes: cx.shared.codes,
                 edition: cx.shared.edition(),
                 playground: &cx.shared.playground,
@@ -552,7 +551,7 @@ fn render_markdown<'a, 'cx: 'a>(
 /// docs are longer, a "Read more" link is appended to the end.
 fn document_short<'a, 'cx: 'a>(
     item: &'a clean::Item,
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     link: AssocItemLink<'a>,
     parent: &'a clean::Item,
     show_def_docs: bool,
@@ -585,7 +584,7 @@ fn document_short<'a, 'cx: 'a>(
 
 fn document_full_collapsible<'a, 'cx: 'a>(
     item: &'a clean::Item,
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     heading_offset: HeadingOffset,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     document_full_inner(item, cx, true, heading_offset)
@@ -593,7 +592,7 @@ fn document_full_collapsible<'a, 'cx: 'a>(
 
 fn document_full<'a, 'cx: 'a>(
     item: &'a clean::Item,
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     heading_offset: HeadingOffset,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     document_full_inner(item, cx, false, heading_offset)
@@ -601,7 +600,7 @@ fn document_full<'a, 'cx: 'a>(
 
 fn document_full_inner<'a, 'cx: 'a>(
     item: &'a clean::Item,
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     is_collapsible: bool,
     heading_offset: HeadingOffset,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
@@ -644,7 +643,7 @@ struct ItemInfo {
 /// * Deprecated
 /// * Required features (through the `doc_cfg` feature)
 fn document_item_info(
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     item: &clean::Item,
     parent: Option<&clean::Item>,
 ) -> ItemInfo {
@@ -690,7 +689,7 @@ enum ShortItemInfo {
 /// the item's documentation.
 fn short_item_info(
     item: &clean::Item,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     parent: Option<&clean::Item>,
 ) -> Vec<ShortItemInfo> {
     let mut extra_info = vec![];
@@ -715,7 +714,8 @@ fn short_item_info(
 
         if let Some(note) = note {
             let note = note.as_str();
-            let html = MarkdownItemInfo(note, &mut cx.id_map);
+            let mut id_map = cx.id_map.borrow_mut();
+            let html = MarkdownItemInfo(note, &mut id_map);
             message.push_str(": ");
             message.push_str(&html.into_string());
         }
@@ -749,18 +749,17 @@ fn short_item_info(
 // Render the list of items inside one of the sections "Trait Implementations",
 // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
 pub(crate) fn render_impls(
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     mut w: impl Write,
     impls: &[&Impl],
     containing_item: &clean::Item,
     toggle_open_by_default: bool,
 ) {
-    let tcx = cx.tcx();
     let mut rendered_impls = impls
         .iter()
         .map(|i| {
             let did = i.trait_did().unwrap();
-            let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx);
+            let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
             let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
             let mut buffer = Buffer::new();
             render_impl(
@@ -906,7 +905,7 @@ fn assoc_method(
     d: &clean::FnDecl,
     link: AssocItemLink<'_>,
     parent: ItemType,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     render_mode: RenderMode,
 ) {
     let tcx = cx.tcx();
@@ -1071,7 +1070,7 @@ fn render_assoc_item(
     item: &clean::Item,
     link: AssocItemLink<'_>,
     parent: ItemType,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     render_mode: RenderMode,
 ) {
     match &item.kind {
@@ -1191,7 +1190,7 @@ fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
 
 pub(crate) fn render_all_impls(
     mut w: impl Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     containing_item: &clean::Item,
     concrete: &[&Impl],
     synthetic: &[&Impl],
@@ -1225,7 +1224,7 @@ pub(crate) fn render_all_impls(
 }
 
 fn render_assoc_items<'a, 'cx: 'a>(
-    cx: &'a mut Context<'cx>,
+    cx: &'a Context<'cx>,
     containing_item: &'a clean::Item,
     it: DefId,
     what: AssocItemRender<'a>,
@@ -1240,15 +1239,14 @@ fn render_assoc_items<'a, 'cx: 'a>(
 
 fn render_assoc_items_inner(
     mut w: &mut dyn fmt::Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
     derefs: &mut DefIdSet,
 ) {
     info!("Documenting associated items of {:?}", containing_item.name);
-    let shared = Rc::clone(&cx.shared);
-    let cache = &shared.cache;
+    let cache = &cx.shared.cache;
     let Some(v) = cache.impls.get(&it) else { return };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
@@ -1276,7 +1274,7 @@ fn render_assoc_items_inner(
                 );
                 tmp_buf.write_str("</summary>");
                 if let Some(def_id) = type_.def_id(cx.cache()) {
-                    cx.deref_id_map.insert(def_id, id);
+                    cx.deref_id_map.borrow_mut().insert(def_id, id);
                 }
                 (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#)
             }
@@ -1340,7 +1338,7 @@ fn render_assoc_items_inner(
 
 fn render_deref_methods(
     mut w: impl Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     impl_: &Impl,
     container_item: &clean::Item,
     deref_mut: bool,
@@ -1407,7 +1405,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
     }
 }
 
-pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
+pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
     let mut has_notable_trait = false;
 
     if ty.is_unit() {
@@ -1450,7 +1448,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
     }
 
     if has_notable_trait {
-        cx.types_with_notable_traits.insert(ty.clone());
+        cx.types_with_notable_traits.borrow_mut().insert(ty.clone());
         Some(format!(
             " <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
             ty = Escape(&format!("{:#}", ty.print(cx))),
@@ -1554,7 +1552,7 @@ struct ImplRenderingParameters {
 
 fn render_impl(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     i: &Impl,
     parent: &clean::Item,
     link: AssocItemLink<'_>,
@@ -1563,8 +1561,7 @@ fn render_impl(
     aliases: &[String],
     rendering_params: ImplRenderingParameters,
 ) {
-    let shared = Rc::clone(&cx.shared);
-    let cache = &shared.cache;
+    let cache = &cx.shared.cache;
     let traits = &cache.traits;
     let trait_ = i.trait_did().map(|did| &traits[&did]);
     let mut close_tags = <Vec<&str>>::with_capacity(2);
@@ -1577,7 +1574,7 @@ fn render_impl(
     fn doc_impl_item(
         boring: &mut Buffer,
         interesting: &mut Buffer,
-        cx: &mut Context<'_>,
+        cx: &Context<'_>,
         item: &clean::Item,
         parent: &clean::Item,
         link: AssocItemLink<'_>,
@@ -1867,7 +1864,7 @@ fn render_impl(
     fn render_default_items(
         boring: &mut Buffer,
         interesting: &mut Buffer,
-        cx: &mut Context<'_>,
+        cx: &Context<'_>,
         t: &clean::Trait,
         i: &clean::Impl,
         parent: &clean::Item,
@@ -1938,6 +1935,23 @@ fn render_impl(
                 if rendering_params.toggle_open_by_default { " open" } else { "" }
             );
         }
+
+        let (before_dox, after_dox) = i
+            .impl_item
+            .opt_doc_value()
+            .map(|dox| {
+                Markdown {
+                    content: &*dox,
+                    links: &i.impl_item.links(cx),
+                    ids: &mut cx.id_map.borrow_mut(),
+                    error_codes: cx.shared.codes,
+                    edition: cx.shared.edition(),
+                    playground: &cx.shared.playground,
+                    heading_offset: HeadingOffset::H4,
+                }
+                .split_summary_and_content()
+            })
+            .unwrap_or((None, None));
         render_impl_summary(
             w,
             cx,
@@ -1946,12 +1960,13 @@ fn render_impl(
             rendering_params.show_def_docs,
             use_absolute,
             aliases,
+            &before_dox,
         );
         if toggled {
             w.write_str("</summary>");
         }
 
-        if let Some(ref dox) = i.impl_item.opt_doc_value() {
+        if before_dox.is_some() {
             if trait_.is_none() && impl_.items.is_empty() {
                 w.write_str(
                     "<div class=\"item-info\">\
@@ -1959,20 +1974,9 @@ fn render_impl(
                      </div>",
                 );
             }
-            write!(
-                w,
-                "<div class=\"docblock\">{}</div>",
-                Markdown {
-                    content: dox,
-                    links: &i.impl_item.links(cx),
-                    ids: &mut cx.id_map,
-                    error_codes: cx.shared.codes,
-                    edition: cx.shared.edition(),
-                    playground: &cx.shared.playground,
-                    heading_offset: HeadingOffset::H4,
-                }
-                .into_string()
-            );
+            if let Some(after_dox) = after_dox {
+                write!(w, "<div class=\"docblock\">{after_dox}</div>");
+            }
         }
         if !default_impl_items.is_empty() || !impl_items.is_empty() {
             w.write_str("<div class=\"impl-items\">");
@@ -2025,7 +2029,7 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render
 
 pub(crate) fn render_impl_summary(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     i: &Impl,
     parent: &clean::Item,
     show_def_docs: bool,
@@ -2033,6 +2037,7 @@ pub(crate) fn render_impl_summary(
     // This argument is used to reference same type with different paths to avoid duplication
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
+    doc: &Option<String>,
 ) {
     let inner_impl = i.inner_impl();
     let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
@@ -2084,6 +2089,10 @@ pub(crate) fn render_impl_summary(
         );
     }
 
+    if let Some(doc) = doc {
+        write!(w, "<div class=\"docblock\">{doc}</div>");
+    }
+
     w.write_str("</section>");
 }
 
@@ -2186,7 +2195,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
 /// implementations that are on concrete or partially generic types, only keeping implementations
 /// of the form `impl<T> Trait for &T`.
 pub(crate) fn get_filtered_impls_for_reference<'a>(
-    shared: &'a Rc<SharedContext<'_>>,
+    shared: &'a SharedContext<'_>,
     it: &clean::Item,
 ) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) {
     let def_id = it.item_id.expect_def_id();
@@ -2423,14 +2432,14 @@ const MAX_FULL_EXAMPLES: usize = 5;
 const NUM_VISIBLE_LINES: usize = 10;
 
 /// Generates the HTML for example call locations generated via the --scrape-examples flag.
-fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) {
+fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean::Item) {
     let tcx = cx.tcx();
     let def_id = item.item_id.expect_def_id();
     let key = tcx.def_path_hash(def_id);
     let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
 
     // Generate a unique ID so users can link to this section for a given method
-    let id = cx.id_map.derive("scraped-examples");
+    let id = cx.derive_id("scraped-examples");
     write!(
         &mut w,
         "<div class=\"docblock scraped-example-list\">\
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index dc205252507..4c8d704e65b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1,7 +1,5 @@
-use std::cell::{RefCell, RefMut};
 use std::cmp::Ordering;
 use std::fmt;
-use std::rc::Rc;
 
 use itertools::Itertools;
 use rinja::Template;
@@ -61,7 +59,7 @@ macro_rules! item_template {
     (
         $(#[$meta:meta])*
         struct $name:ident<'a, 'cx> {
-            cx: RefCell<&'a mut Context<'cx>>,
+            cx: &'a Context<'cx>,
             it: &'a clean::Item,
             $($field_name:ident: $field_ty:ty),*,
         },
@@ -70,14 +68,14 @@ macro_rules! item_template {
         #[derive(Template)]
         $(#[$meta])*
         struct $name<'a, 'cx> {
-            cx: RefCell<&'a mut Context<'cx>>,
+            cx: &'a Context<'cx>,
             it: &'a clean::Item,
             $($field_name: $field_ty),*
         }
 
         impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> {
-            fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
-                (&self.it, self.cx.borrow_mut())
+            fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>) {
+                (&self.it, &self.cx)
             }
         }
 
@@ -95,8 +93,8 @@ macro_rules! item_template_methods {
     (document $($rest:tt)*) => {
         fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let (item, mut cx) = self.item_and_mut_cx();
-                let v = document(*cx, item, None, HeadingOffset::H2);
+                let (item, cx) = self.item_and_cx();
+                let v = document(cx, item, None, HeadingOffset::H2);
                 write!(f, "{v}")
             })
         }
@@ -105,9 +103,9 @@ macro_rules! item_template_methods {
     (document_type_layout $($rest:tt)*) => {
         fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let (item, cx) = self.item_and_mut_cx();
+                let (item, cx) = self.item_and_cx();
                 let def_id = item.item_id.expect_def_id();
-                let v = document_type_layout(*cx, def_id);
+                let v = document_type_layout(cx, def_id);
                 write!(f, "{v}")
             })
         }
@@ -116,8 +114,8 @@ macro_rules! item_template_methods {
     (render_attributes_in_pre $($rest:tt)*) => {
         fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let (item, cx) = self.item_and_mut_cx();
-                let v = render_attributes_in_pre(item, "", &cx);
+                let (item, cx) = self.item_and_cx();
+                let v = render_attributes_in_pre(item, "", cx);
                 write!(f, "{v}")
             })
         }
@@ -126,9 +124,9 @@ macro_rules! item_template_methods {
     (render_assoc_items $($rest:tt)*) => {
         fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let (item, mut cx) = self.item_and_mut_cx();
+                let (item, cx) = self.item_and_cx();
                 let def_id = item.item_id.expect_def_id();
-                let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All);
+                let v = render_assoc_items(cx, item, def_id, AssocItemRender::All);
                 write!(f, "{v}")
             })
         }
@@ -175,7 +173,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
     len_before != buffer.len()
 }
 
-pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
+pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
     debug_assert!(!item.is_stripped());
     let typ = match item.kind {
         clean::ModuleItem(_) => {
@@ -223,7 +221,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
     // this page, and this link will be auto-clicked. The `id` attribute is
     // used to find the link to auto-click.
     let src_href =
-        if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
+        if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
 
     let path_components = if item.is_primitive() || item.is_keyword() {
         vec![]
@@ -277,13 +275,14 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
     }
 
     // Render notable-traits.js used for all methods in this module.
-    if !cx.types_with_notable_traits.is_empty() {
+    let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut();
+    if !types_with_notable_traits.is_empty() {
         write!(
             buf,
             r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
-            notable_traits_json(cx.types_with_notable_traits.iter(), cx)
+            notable_traits_json(types_with_notable_traits.iter(), cx)
         );
-        cx.types_with_notable_traits.clear();
+        types_with_notable_traits.clear();
     }
 }
 
@@ -308,10 +307,10 @@ fn toggle_close(mut w: impl fmt::Write) {
 }
 
 trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
-    fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
+    fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>);
 }
 
-fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
+fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
     write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
 
     let mut not_stripped_items =
@@ -594,7 +593,7 @@ fn extra_info_tags<'a, 'tcx: 'a>(
     })
 }
 
-fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
+fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
     let tcx = cx.tcx();
     let header = it.fn_header(tcx).expect("printing a function which isn't a function");
     debug!(
@@ -649,7 +648,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 }
 
-fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
+fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
     let tcx = cx.tcx();
     let bounds = bounds(&t.bounds, false, cx);
     let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
@@ -801,7 +800,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     // Trait documentation
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
-    fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
+    fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
         let name = m.name.unwrap();
         info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
         let item_type = m.type_();
@@ -929,8 +928,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     // If there are methods directly on this trait object, render them here.
     write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All));
 
-    let cloned_shared = Rc::clone(&cx.shared);
-    let cache = &cloned_shared.cache;
     let mut extern_crates = FxIndexSet::default();
 
     if !t.is_dyn_compatible(cx.tcx()) {
@@ -950,12 +947,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         );
     }
 
-    if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
+    if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
         for implementor in implementors {
-            if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache)
+            if let Some(did) =
+                implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache)
                 && !did.is_local()
             {
                 extern_crates.insert(did.krate);
@@ -1036,7 +1034,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
                     it,
                     w,
                     &implementor_dups,
-                    &collect_paths_for_type(implementor.inner_impl().for_.clone(), cache),
+                    &collect_paths_for_type(
+                        implementor.inner_impl().for_.clone(),
+                        &cx.shared.cache,
+                    ),
                 );
             }
             w.write_str("</div>");
@@ -1139,8 +1140,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         .chain(std::iter::once("trait.impl"))
         .collect();
     if let Some(did) = it.item_id.as_def_id()
-        && let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) }
-        && let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern)
+        && let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) }
+        && let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern)
     {
         js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
         js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
@@ -1164,7 +1165,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
 fn item_trait_alias(
     w: &mut impl fmt::Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     t: &clean::TraitAlias,
 ) {
@@ -1190,7 +1191,7 @@ fn item_trait_alias(
         .unwrap();
 }
 
-fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
+fn item_type_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
     wrap_item(w, |w| {
         write!(
             w,
@@ -1355,8 +1356,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
     //
     // [JSONP]: https://en.wikipedia.org/wiki/JSONP
     // [^115718]: https://github.com/rust-lang/rust/issues/115718
-    let cloned_shared = Rc::clone(&cx.shared);
-    let cache = &cloned_shared.cache;
+    let cache = &cx.shared.cache;
     if let Some(target_did) = t.type_.def_id(cache) &&
         let get_extern = { || cache.external_paths.get(&target_did) } &&
         let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) &&
@@ -1380,11 +1380,11 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
     }
 }
 
-fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
+fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
     item_template!(
         #[template(path = "item_union.html")]
         struct ItemUnion<'a, 'cx> {
-            cx: RefCell<&'a mut Context<'cx>>,
+            cx: &'a Context<'cx>,
             it: &'a clean::Item,
             s: &'a clean::Union,
         },
@@ -1394,8 +1394,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
     impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
         fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let cx = self.cx.borrow_mut();
-                let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx);
+                let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx);
                 write!(f, "{v}")
             })
         }
@@ -1405,15 +1404,13 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
             field: &'a clean::Item,
         ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let mut cx = self.cx.borrow_mut();
-                let v = document(*cx, field, Some(self.it), HeadingOffset::H3);
+                let v = document(self.cx, field, Some(self.it), HeadingOffset::H3);
                 write!(f, "{v}")
             })
         }
 
         fn stability_field(&self, field: &clean::Item) -> Option<String> {
-            let cx = self.cx.borrow();
-            field.stability_class(cx.tcx())
+            field.stability_class(self.cx.tcx())
         }
 
         fn print_ty<'b>(
@@ -1421,8 +1418,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
             ty: &'a clean::Type,
         ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
-                let cx = self.cx.borrow();
-                let v = ty.print(*cx);
+                let v = ty.print(&self.cx);
                 write!(f, "{v}")
             })
         }
@@ -1441,7 +1437,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
         }
     }
 
-    ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap();
+    ItemUnion { cx, it, s }.render_into(w).unwrap();
 }
 
 fn print_tuple_struct_fields<'a, 'cx: 'a>(
@@ -1471,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
     })
 }
 
-fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
+fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
     let count_variants = e.variants().count();
     wrap_item(w, |w| {
         render_attributes_in_code(w, it, cx);
@@ -1532,7 +1528,7 @@ fn should_show_enum_discriminant(
 
 fn display_c_like_variant(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     item: &clean::Item,
     variant: &clean::Variant,
     index: VariantIdx,
@@ -1557,7 +1553,7 @@ fn display_c_like_variant(
 
 fn render_enum_fields(
     mut w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     g: Option<&clean::Generics>,
     variants: &IndexVec<VariantIdx, clean::Item>,
     count_variants: usize,
@@ -1621,7 +1617,7 @@ fn render_enum_fields(
 
 fn item_variants(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     variants: &IndexVec<VariantIdx, clean::Item>,
     enum_def_id: DefId,
@@ -1743,7 +1739,7 @@ fn item_variants(
     write!(w, "</div>");
 }
 
-fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
+fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
     wrap_item(w, |w| {
         // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
         if !t.macro_rules {
@@ -1756,7 +1752,7 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
 fn item_proc_macro(
     w: &mut impl fmt::Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     m: &clean::ProcMacro,
 ) {
@@ -1790,7 +1786,7 @@ fn item_proc_macro(
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
 }
 
-fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
+fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
     let def_id = it.item_id.expect_def_id();
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
     if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
@@ -1798,8 +1794,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
     } else {
         // We handle the "reference" primitive type on its own because we only want to list
         // implementations on generic types.
-        let shared = Rc::clone(&cx.shared);
-        let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
+        let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it);
 
         render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
     }
@@ -1807,7 +1802,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
 
 fn item_constant(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     generics: &clean::Generics,
     ty: &clean::Type,
@@ -1862,7 +1857,7 @@ fn item_constant(
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
-fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
+fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
     wrap_item(w, |w| {
         render_attributes_in_code(w, it, cx);
         render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
@@ -1879,7 +1874,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
 
 fn item_fields(
     w: &mut Buffer,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     fields: &[clean::Item],
     ctor_kind: Option<CtorKind>,
@@ -1920,7 +1915,7 @@ fn item_fields(
 
 fn item_static(
     w: &mut impl fmt::Write,
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     it: &clean::Item,
     s: &clean::Static,
     safety: Option<hir::Safety>,
@@ -1944,7 +1939,7 @@ fn item_static(
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
 }
 
-fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
+fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
     wrap_item(w, |buffer| {
         buffer.write_str("extern {\n").unwrap();
         render_attributes_in_code(buffer, it, cx);
@@ -1962,7 +1957,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::
         .unwrap();
 }
 
-fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
+fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
@@ -2134,7 +2129,7 @@ impl Ord for ImplString {
 }
 
 fn render_implementor(
-    cx: &mut Context<'_>,
+    cx: &Context<'_>,
     implementor: &Impl,
     trait_: &clean::Item,
     w: &mut Buffer,
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 76de8d87231..e99e2f04b2c 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,10 +1,9 @@
 use std::borrow::Cow;
-use std::rc::Rc;
 
 use rinja::Template;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::CtorKind;
-use rustc_hir::def_id::DefIdSet;
+use rustc_hir::def_id::{DefIdMap, DefIdSet};
 use rustc_middle::ty::{self, TyCtxt};
 use tracing::debug;
 
@@ -119,17 +118,18 @@ pub(crate) mod filters {
 pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     let mut ids = IdMap::new();
     let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
+    let deref_id_map = cx.deref_id_map.borrow();
     match it.kind {
-        clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks),
-        clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks),
-        clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks),
-        clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks),
-        clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks),
-        clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks),
+        clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks, &deref_id_map),
+        clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks, &deref_id_map),
+        clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks, &deref_id_map),
+        clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks, &deref_id_map),
+        clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks, &deref_id_map),
+        clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks, &deref_id_map),
         clean::ModuleItem(ref m) => {
             blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it)))
         }
-        clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks),
+        clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks, &deref_id_map),
         _ => {}
     }
     // The sidebar is designed to display sibling functions, modules and
@@ -245,6 +245,7 @@ fn sidebar_struct<'a>(
     it: &'a clean::Item,
     s: &'a clean::Struct,
     items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     let fields = get_struct_fields_name(&s.fields);
     let field_name = match s.ctor_kind {
@@ -255,7 +256,7 @@ fn sidebar_struct<'a>(
     if let Some(name) = field_name {
         items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields));
     }
-    sidebar_assoc_items(cx, it, items);
+    sidebar_assoc_items(cx, it, items, deref_id_map);
 }
 
 fn sidebar_trait<'a>(
@@ -263,6 +264,7 @@ fn sidebar_trait<'a>(
     it: &'a clean::Item,
     t: &'a clean::Trait,
     blocks: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     fn filter_items<'a>(
         items: &'a [clean::Item],
@@ -313,7 +315,7 @@ fn sidebar_trait<'a>(
         .into_iter()
         .map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)),
     );
-    sidebar_assoc_items(cx, it, blocks);
+    sidebar_assoc_items(cx, it, blocks, deref_id_map);
 
     if !t.is_dyn_compatible(cx.tcx()) {
         blocks.push(LinkBlock::forced(
@@ -331,13 +333,17 @@ fn sidebar_trait<'a>(
     }
 }
 
-fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>) {
+fn sidebar_primitive<'a>(
+    cx: &'a Context<'_>,
+    it: &'a clean::Item,
+    items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
+) {
     if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
-        sidebar_assoc_items(cx, it, items);
+        sidebar_assoc_items(cx, it, items, deref_id_map);
     } else {
-        let shared = Rc::clone(&cx.shared);
         let (concrete, synthetic, blanket_impl) =
-            super::get_filtered_impls_for_reference(&shared, it);
+            super::get_filtered_impls_for_reference(&cx.shared, it);
 
         sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items);
     }
@@ -348,6 +354,7 @@ fn sidebar_type_alias<'a>(
     it: &'a clean::Item,
     t: &'a clean::TypeAlias,
     items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     if let Some(inner_type) = &t.inner_type {
         items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type"));
@@ -370,7 +377,7 @@ fn sidebar_type_alias<'a>(
             }
         }
     }
-    sidebar_assoc_items(cx, it, items);
+    sidebar_assoc_items(cx, it, items, deref_id_map);
 }
 
 fn sidebar_union<'a>(
@@ -378,10 +385,11 @@ fn sidebar_union<'a>(
     it: &'a clean::Item,
     u: &'a clean::Union,
     items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     let fields = get_struct_fields_name(&u.fields);
     items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields));
-    sidebar_assoc_items(cx, it, items);
+    sidebar_assoc_items(cx, it, items, deref_id_map);
 }
 
 /// Adds trait implementations into the blocks of links
@@ -389,6 +397,7 @@ fn sidebar_assoc_items<'a>(
     cx: &'a Context<'_>,
     it: &'a clean::Item,
     links: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     let did = it.item_id.expect_def_id();
     let cache = cx.cache();
@@ -433,7 +442,15 @@ fn sidebar_assoc_items<'a>(
             {
                 let mut derefs = DefIdSet::default();
                 derefs.insert(did);
-                sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links);
+                sidebar_deref_methods(
+                    cx,
+                    &mut blocks,
+                    impl_,
+                    v,
+                    &mut derefs,
+                    &mut used_links,
+                    deref_id_map,
+                );
             }
 
             let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
@@ -462,6 +479,7 @@ fn sidebar_deref_methods<'a>(
     v: &[Impl],
     derefs: &mut DefIdSet,
     used_links: &mut FxHashSet<String>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     let c = cx.cache();
 
@@ -501,7 +519,7 @@ fn sidebar_deref_methods<'a>(
             if !ret.is_empty() {
                 let id = if let Some(target_def_id) = real_target.def_id(c) {
                     Cow::Borrowed(
-                        cx.deref_id_map
+                        deref_id_map
                             .get(&target_def_id)
                             .expect("Deref section without derived id")
                             .as_str(),
@@ -531,7 +549,15 @@ fn sidebar_deref_methods<'a>(
                     .unwrap_or(false)
             })
         {
-            sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links);
+            sidebar_deref_methods(
+                cx,
+                out,
+                target_deref_impl,
+                target_impls,
+                derefs,
+                used_links,
+                deref_id_map,
+            );
         }
     }
 }
@@ -541,6 +567,7 @@ fn sidebar_enum<'a>(
     it: &'a clean::Item,
     e: &'a clean::Enum,
     items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
     let mut variants = e
         .variants()
@@ -550,7 +577,7 @@ fn sidebar_enum<'a>(
     variants.sort_unstable();
 
     items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants));
-    sidebar_assoc_items(cx, it, items);
+    sidebar_assoc_items(cx, it, items, deref_id_map);
 }
 
 pub(crate) fn sidebar_module_like(
@@ -607,8 +634,9 @@ fn sidebar_foreign_type<'a>(
     cx: &'a Context<'_>,
     it: &'a clean::Item,
     items: &mut Vec<LinkBlock<'a>>,
+    deref_id_map: &'a DefIdMap<String>,
 ) {
-    sidebar_assoc_items(cx, it, items);
+    sidebar_assoc_items(cx, it, items, deref_id_map);
 }
 
 /// Renders the trait implementations for this type
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 7c676469597..ce10e5ecc24 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -43,7 +43,6 @@ use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge};
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::Impl;
-use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::format::Buffer;
 use crate::html::layout;
@@ -62,13 +61,12 @@ pub(crate) fn write_shared(
     tcx: TyCtxt<'_>,
 ) -> Result<(), Error> {
     // NOTE(EtomicBomb): I don't think we need sync here because no read-after-write?
-    Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
+    cx.shared.fs.set_sync_only(true);
     let lock_file = cx.dst.join(".lock");
     // Write shared runs within a flock; disable thread dispatching of IO temporarily.
     let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
 
-    let SerializedSearchIndex { index, desc } =
-        build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
+    let SerializedSearchIndex { index, desc } = build_index(krate, &mut cx.shared.cache, tcx);
     write_search_desc(cx, krate, &desc)?; // does not need to be merged
 
     let crate_name = krate.name(cx.tcx());
@@ -104,7 +102,7 @@ pub(crate) fn write_shared(
             &cx.shared.style_files,
             cx.shared.layout.css_file_extension.as_deref(),
             &cx.shared.resource_suffix,
-            cx.include_sources,
+            cx.info.include_sources,
         )?;
         match &opt.index_page {
             Some(index_page) if opt.enable_index_page => {
@@ -128,7 +126,7 @@ pub(crate) fn write_shared(
         }
     }
 
-    Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
+    cx.shared.fs.set_sync_only(false);
     Ok(())
 }
 
@@ -597,13 +595,11 @@ impl TypeAliasPart {
         krate: &Crate,
         crate_name_json: &OrderedJson,
     ) -> Result<PartsAndLocations<Self>, Error> {
-        let cache = &Rc::clone(&cx.shared).cache;
         let mut path_parts = PartsAndLocations::default();
 
         let mut type_impl_collector = TypeImplCollector {
             aliased_types: IndexMap::default(),
             visited_aliases: FxHashSet::default(),
-            cache,
             cx,
         };
         DocVisitor::visit_crate(&mut type_impl_collector, krate);
@@ -625,14 +621,14 @@ impl TypeAliasPart {
                     // each type alias, and if it gives a different result, split the impl
                     for &(type_alias_fqp, type_alias_item) in type_aliases {
                         let mut buf = Buffer::html();
-                        cx.id_map = Default::default();
-                        cx.deref_id_map = Default::default();
+                        cx.id_map.borrow_mut().clear();
+                        cx.deref_id_map.borrow_mut().clear();
                         let target_did = impl_
                             .inner_impl()
                             .trait_
                             .as_ref()
                             .map(|trait_| trait_.def_id())
-                            .or_else(|| impl_.inner_impl().for_.def_id(cache));
+                            .or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
                         let provided_methods;
                         let assoc_link = if let Some(target_did) = target_did {
                             provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx());
@@ -720,7 +716,7 @@ impl TraitAliasPart {
     }
 
     fn get(
-        cx: &mut Context<'_>,
+        cx: &Context<'_>,
         crate_name_json: &OrderedJson,
     ) -> Result<PartsAndLocations<Self>, Error> {
         let cache = &cx.shared.cache;
@@ -828,8 +824,7 @@ struct TypeImplCollector<'cx, 'cache, 'item> {
     /// Map from DefId-of-aliased-type to its data.
     aliased_types: IndexMap<DefId, AliasedType<'cache, 'item>>,
     visited_aliases: FxHashSet<DefId>,
-    cache: &'cache Cache,
-    cx: &'cache mut Context<'cx>,
+    cx: &'cache Context<'cx>,
 }
 
 /// Data for an aliased type.
@@ -868,7 +863,7 @@ struct AliasedTypeImpl<'cache, 'item> {
 impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> {
     fn visit_item(&mut self, it: &'item Item) {
         self.visit_item_recur(it);
-        let cache = self.cache;
+        let cache = &self.cx.shared.cache;
         let ItemKind::TypeAliasItem(ref t) = it.kind else { return };
         let Some(self_did) = it.item_id.as_def_id() else { return };
         if !self.visited_aliases.insert(self_did) {
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 2fe9364c259..9827f97d28d 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -2,7 +2,6 @@ use std::cell::RefCell;
 use std::ffi::OsStr;
 use std::ops::RangeInclusive;
 use std::path::{Component, Path, PathBuf};
-use std::rc::Rc;
 use std::{fmt, fs};
 
 use rinja::Template;
@@ -10,7 +9,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::{FileName, sym};
+use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, sym};
 use tracing::info;
 
 use crate::clean;
@@ -51,8 +50,14 @@ struct LocalSourcesCollector<'a, 'tcx> {
     src_root: &'a Path,
 }
 
-fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
-    span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
+fn filename_real_and_local(span: clean::Span, sess: &Session) -> Option<RealFileName> {
+    if span.cnum(sess) == LOCAL_CRATE
+        && let FileName::Real(file) = span.filename(sess)
+    {
+        Some(file)
+    } else {
+        None
+    }
 }
 
 impl LocalSourcesCollector<'_, '_> {
@@ -61,16 +66,8 @@ impl LocalSourcesCollector<'_, '_> {
         let span = item.span(self.tcx);
         let Some(span) = span else { return };
         // skip all synthetic "files"
-        if !is_real_and_local(span, sess) {
-            return;
-        }
-        let filename = span.filename(sess);
-        let p = if let FileName::Real(file) = filename {
-            match file.into_local_path() {
-                Some(p) => p,
-                None => return,
-            }
-        } else {
+        let Some(p) = filename_real_and_local(span, sess).and_then(|file| file.into_local_path())
+        else {
             return;
         };
         if self.local_sources.contains_key(&*p) {
@@ -124,7 +121,7 @@ struct SourceCollector<'a, 'tcx> {
 
 impl DocVisitor<'_> for SourceCollector<'_, '_> {
     fn visit_item(&mut self, item: &clean::Item) {
-        if !self.cx.include_sources {
+        if !self.cx.info.include_sources {
             return;
         }
 
@@ -136,8 +133,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
         // If we're not rendering sources, there's nothing to do.
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
-        if is_real_and_local(span, sess) {
-            let filename = span.filename(sess);
+        if let Some(filename) = filename_real_and_local(span, sess) {
             let span = span.inner();
             let pos = sess.source_map().lookup_source_file(span.lo());
             let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_position());
@@ -146,14 +142,14 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
             // something like that), so just don't include sources for the
             // entire crate. The other option is maintaining this mapping on a
             // per-file basis, but that's probably not worth it...
-            self.cx.include_sources = match self.emit_source(&filename, file_span) {
+            self.cx.info.include_sources = match self.emit_source(&filename, file_span) {
                 Ok(()) => true,
                 Err(e) => {
                     self.cx.shared.tcx.dcx().span_err(
                         span,
                         format!(
                             "failed to render source code for `{filename}`: {e}",
-                            filename = filename.prefer_local(),
+                            filename = filename.to_string_lossy(FileNameDisplayPreference::Local),
                         ),
                     );
                     false
@@ -169,18 +165,13 @@ impl SourceCollector<'_, '_> {
     /// Renders the given filename into its corresponding HTML source file.
     fn emit_source(
         &mut self,
-        filename: &FileName,
+        file: &RealFileName,
         file_span: rustc_span::Span,
     ) -> Result<(), Error> {
-        let p = match *filename {
-            FileName::Real(ref file) => {
-                if let Some(local_path) = file.local_path() {
-                    local_path.to_path_buf()
-                } else {
-                    unreachable!("only the current crate should have sources emitted");
-                }
-            }
-            _ => return Ok(()),
+        let p = if let Some(local_path) = file.local_path() {
+            local_path.to_path_buf()
+        } else {
+            unreachable!("only the current crate should have sources emitted");
         };
         if self.emitted_local_sources.contains(&*p) {
             // We've already emitted this source
@@ -197,7 +188,7 @@ impl SourceCollector<'_, '_> {
         // Remove the utf-8 BOM if any
         let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
 
-        let shared = Rc::clone(&self.cx.shared);
+        let shared = &self.cx.shared;
         // Create the intermediate directories
         let cur = RefCell::new(PathBuf::new());
         let root_path = RefCell::new(PathBuf::new());
@@ -234,8 +225,10 @@ impl SourceCollector<'_, '_> {
         cur.push(&fname);
 
         let title = format!("{} - source", src_fname.to_string_lossy());
-        let desc =
-            format!("Source of the Rust file `{}`.", filename.prefer_remapped_unconditionaly());
+        let desc = format!(
+            "Source of the Rust file `{}`.",
+            file.to_string_lossy(FileNameDisplayPreference::Remapped)
+        );
         let page = layout::Page {
             title: &title,
             css_class: "src",
@@ -250,12 +243,11 @@ impl SourceCollector<'_, '_> {
             &page,
             "",
             |buf: &mut _| {
-                let cx = &mut self.cx;
                 print_src(
                     buf,
                     contents,
                     file_span,
-                    cx,
+                    self.cx,
                     &root_path,
                     highlight::DecorationInfo::default(),
                     SourceContext::Standalone { file_path },
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 66a8a198928..27496381b2c 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -36,6 +36,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	--button-border-radius: 2px;
 	--toolbar-button-border-radius: 6px;
 	--code-block-border-radius: 6px;
+	--impl-items-indent: 0.3em;
+	--docblock-indent: 24px;
 }
 
 /* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -909,7 +911,7 @@ both the code example and the line numbers, so we need to remove the radius in t
 .docblock h6 { font-size: 0.875rem; }
 
 .docblock {
-	margin-left: 24px;
+	margin-left: var(--docblock-indent);
 	position: relative;
 }
 
@@ -982,7 +984,11 @@ div.where {
 
 .item-info {
 	display: block;
-	margin-left: 24px;
+	margin-left: var(--docblock-indent);
+}
+.impl-items > .item-info {
+	/* Margin of docblocks + margin of impl block items. */
+	margin-left: calc(var(--docblock-indent) + var(--impl-items-indent));
 }
 
 .item-info code {
@@ -2166,6 +2172,15 @@ details.toggle > summary:not(.hideme)::before {
 	left: -24px;
 }
 
+/* We indent items of an impl block to have a visual marker that these items are part
+	of this impl block. */
+.impl-items > *:not(.item-info),
+/* We also indent the first top doc comment the same to still keep an indent on the
+	doc block while aligning it with the impl block items. */
+.implementors-toggle > .docblock {
+	margin-left: var(--impl-items-indent);
+}
+
 details.big-toggle > summary:not(.hideme)::before {
 	left: -34px;
 	top: 9px;
@@ -2195,6 +2210,39 @@ details.toggle[open] > summary::after {
 	content: "Collapse";
 }
 
+details.toggle:not([open]) > summary .docblock {
+	max-height: calc(1.5em + 0.75em);
+	overflow-y: hidden;
+}
+details.toggle:not([open]) > summary .docblock > :first-child {
+	max-width: 100%;
+	overflow: hidden;
+	width: fit-content;
+	white-space: nowrap;
+	position: relative;
+	padding-right: 1em;
+}
+details.toggle:not([open]) > summary .docblock > :first-child::after {
+	content: "…";
+	position: absolute;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	z-index: 1;
+	background-color: var(--main-background-color);
+	font: 1rem/1.5 "Source Serif 4", NanumBarunGothic, serif;
+	/* To make it look a bit better and not have it stuck to the preceding element. */
+	padding-left: 0.2em;
+}
+details.toggle:not([open]) > summary .docblock > div:first-child::after {
+	/* This is to make the "..." always appear at the bottom. */
+	padding-top: calc(1.5em + 0.75em - 1.2rem);
+}
+
+details.toggle > summary .docblock {
+	margin-top: 0.75em;
+}
+
 /* This is needed in docblocks to have the "▶" element to be on the same line. */
 .docblock summary > * {
 	display: inline-block;
@@ -2255,6 +2303,10 @@ If you update this line, then you also need to update the line with the same war
 in src-script.js and main.js
 */
 @media (max-width: 700px) {
+	:root {
+		--impl-items-indent: 0.7em;
+	}
+
 	/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
 	   or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured
 	   by the topbar. Anything with an `id` gets scroll-margin-top equal to .mobile-topbar's size.
@@ -2454,19 +2506,20 @@ in src-script.js and main.js
 		padding-top: 0;
 	}
 
-	/* Position of the "[-]" element. */
-	details.toggle:not(.top-doc) > summary, .impl-items > section  {
+	details.implementors-toggle:not(.top-doc) > summary  {
 		margin-left: 10px;
 	}
-	.impl-items > details.toggle > summary:not(.hideme)::before,
-	#main-content > details.toggle:not(.top-doc) > summary::before,
-	#main-content > div > details.toggle > summary::before {
-		left: -11px;
+
+	.impl-items > details.toggle > summary:not(.hideme)::before {
+		left: -20px;
 	}
 
 	/* Align summary-nested and unnested item-info gizmos. */
+	summary > .item-info {
+		margin-left: 10px;
+	}
 	.impl-items > .item-info {
-		margin-left: 34px;
+		margin-left: calc(var(--impl-items-indent) + 10px);
 	}
 
 	.src nav.sub {
@@ -2500,24 +2553,24 @@ in src-script.js and main.js
 }
 
 @media print {
+	:root {
+		--docblock-indent: 0;
+	}
+
 	nav.sidebar, nav.sub, .out-of-band, a.src, #copy-path,
 	details.toggle[open] > summary::before, details.toggle > summary::before,
 	details.toggle.top-doc > summary {
 		display: none;
 	}
 
-	.docblock {
-		margin-left: 0;
-	}
-
 	main {
 		padding: 10px;
 	}
 }
 
 @media (max-width: 464px) {
-	.docblock {
-		margin-left: 12px;
+	:root {
+		--docblock-indent: 12px;
 	}
 
 	.docblock code {
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 1c8303d4c20..bb967b7f163 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
         MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
         TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)),
         ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
-        StaticItem(s) => ItemEnum::Static(s.into_json(renderer)),
-        ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)),
+        StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
+        ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
         ForeignTypeItem => ItemEnum::ExternType,
         TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
         // FIXME(generic_const_items): Add support for generic free consts
@@ -831,17 +831,20 @@ impl FromClean<Box<clean::TypeAlias>> for TypeAlias {
     }
 }
 
-impl FromClean<clean::Static> for Static {
-    fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self {
-        let tcx = renderer.tcx;
-        Static {
-            type_: (*stat.type_).into_json(renderer),
-            is_mutable: stat.mutability == ast::Mutability::Mut,
-            expr: stat
-                .expr
-                .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
-                .unwrap_or_default(),
-        }
+fn convert_static(
+    stat: clean::Static,
+    safety: rustc_hir::Safety,
+    renderer: &JsonRenderer<'_>,
+) -> Static {
+    let tcx = renderer.tcx;
+    Static {
+        type_: (*stat.type_).into_json(renderer),
+        is_mutable: stat.mutability == ast::Mutability::Mut,
+        is_unsafe: safety == rustc_hir::Safety::Unsafe,
+        expr: stat
+            .expr
+            .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
+            .unwrap_or_default(),
     }
 }
 
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 560ed872ef3..789a5614967 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     }
 
     const RUN_ON_MODULE: bool = false;
+    type ModuleData = ();
 
     fn init(
         krate: clean::Crate,
@@ -161,8 +162,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         ))
     }
 
-    fn make_child_renderer(&self) -> Self {
-        self.clone()
+    fn save_module_data(&mut self) -> Self::ModuleData {
+        unreachable!("RUN_ON_MODULE = false, should never call save_module_data")
+    }
+    fn restore_module_data(&mut self, _info: Self::ModuleData) {
+        unreachable!("RUN_ON_MODULE = false, should never call set_back_info")
     }
 
     /// Inserts an item into the index. This should be used rather than directly calling insert on
@@ -243,7 +247,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     }
 
     fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> {
-        unreachable!("RUN_ON_MODULE = false should never call mod_item_in")
+        unreachable!("RUN_ON_MODULE = false, should never call mod_item_in")
     }
 
     fn after_krate(&mut self) -> Result<(), Error> {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 436d36d899e..a384c286039 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -68,7 +68,7 @@ extern crate test;
 // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
 // about jemalloc.
 #[cfg(feature = "jemalloc")]
-extern crate jemalloc_sys;
+extern crate tikv_jemalloc_sys as jemalloc_sys;
 
 use std::env::{self, VarError};
 use std::io::{self, IsTerminal};
@@ -76,7 +76,7 @@ use std::process;
 use std::sync::Arc;
 use std::sync::atomic::AtomicBool;
 
-use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
+use rustc_errors::DiagCtxtHandle;
 use rustc_interface::interface;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@@ -179,7 +179,8 @@ pub fn main() {
 
     let exit_code = rustc_driver::catch_with_exit_code(|| {
         let at_args = rustc_driver::args::raw_args(&early_dcx)?;
-        main_args(&mut early_dcx, &at_args, using_internal_features)
+        main_args(&mut early_dcx, &at_args, using_internal_features);
+        Ok(())
     });
     process::exit(exit_code);
 }
@@ -699,13 +700,10 @@ fn usage(argv0: &str) {
     );
 }
 
-/// A result type used by several functions under `main()`.
-type MainResult = Result<(), ErrorGuaranteed>;
-
-pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) -> MainResult {
+pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) {
     match res {
-        Ok(()) => dcx.has_errors().map_or(Ok(()), Err),
-        Err(err) => Err(dcx.err(err)),
+        Ok(()) => dcx.abort_if_errors(),
+        Err(err) => dcx.fatal(err),
     }
 }
 
@@ -714,17 +712,17 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
     renderopts: config::RenderOptions,
     cache: formats::cache::Cache,
     tcx: TyCtxt<'tcx>,
-) -> MainResult {
+) {
     match formats::run_format::<T>(krate, renderopts, cache, tcx) {
-        Ok(_) => tcx.dcx().has_errors().map_or(Ok(()), Err),
+        Ok(_) => tcx.dcx().abort_if_errors(),
         Err(e) => {
             let mut msg =
-                tcx.dcx().struct_err(format!("couldn't generate documentation: {}", e.error));
+                tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error));
             let file = e.file.display().to_string();
             if !file.is_empty() {
                 msg.note(format!("failed to create or modify \"{file}\""));
             }
-            Err(msg.emit())
+            msg.emit();
         }
     }
 }
@@ -759,7 +757,7 @@ fn main_args(
     early_dcx: &mut EarlyDiagCtxt,
     at_args: &[String],
     using_internal_features: Arc<AtomicBool>,
-) -> MainResult {
+) {
     // Throw away the first argument, the name of the binary.
     // In case of at_args being empty, as might be the case by
     // passing empty argument array to execve under some platforms,
@@ -770,7 +768,7 @@ fn main_args(
     // the compiler with @empty_file as argv[0] and no more arguments.
     let at_args = at_args.get(1..).unwrap_or_default();
 
-    let args = rustc_driver::args::arg_expand_all(early_dcx, at_args)?;
+    let args = rustc_driver::args::arg_expand_all(early_dcx, at_args);
 
     let mut options = getopts::Options::new();
     for option in opts() {
@@ -788,7 +786,7 @@ fn main_args(
     let (input, options, render_options) =
         match config::Options::from_matches(early_dcx, &matches, args) {
             Some(opts) => opts,
-            None => return Ok(()),
+            None => return,
         };
 
     let dcx =
@@ -853,11 +851,11 @@ fn main_args(
 
         if sess.opts.describe_lints {
             rustc_driver::describe_lints(sess);
-            return Ok(());
+            return;
         }
 
         compiler.enter(|queries| {
-            let Ok(mut gcx) = queries.global_ctxt() else { FatalError.raise() };
+            let mut gcx = queries.global_ctxt();
             if sess.dcx().has_errors().is_some() {
                 sess.dcx().fatal("Compilation failed, aborting rustdoc");
             }
@@ -865,7 +863,7 @@ fn main_args(
             gcx.enter(|tcx| {
                 let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
                     core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
-                })?;
+                });
                 info!("finished with rustc");
 
                 if let Some(options) = scrape_examples_options {
@@ -884,10 +882,10 @@ fn main_args(
                 if show_coverage {
                     // if we ran coverage, bail early, we don't need to also generate docs at this point
                     // (also we didn't load in any of the useful passes)
-                    return Ok(());
+                    return;
                 } else if run_check {
                     // Since we're in "check" mode, no need to generate anything beyond this point.
-                    return Ok(());
+                    return;
                 }
 
                 info!("going to format");
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index bf851b278b8..c288a3cf2a4 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -60,8 +60,6 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
             item.kind,
             clean::StructFieldItem(_)
                 | clean::VariantItem(_)
-                | clean::AssocConstItem(..)
-                | clean::AssocTypeItem(..)
                 | clean::TypeAliasItem(_)
                 | clean::StaticItem(_)
                 | clean::ConstantItem(..)
@@ -69,6 +67,15 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
                 | clean::ImportItem(_)
                 | clean::PrimitiveItem(_)
                 | clean::KeywordItem
+                | clean::ModuleItem(_)
+                | clean::TraitAliasItem(_)
+                | clean::ForeignFunctionItem(..)
+                | clean::ForeignStaticItem(..)
+                | clean::ForeignTypeItem
+                | clean::AssocConstItem(..)
+                | clean::AssocTypeItem(..)
+                | clean::TyAssocConstItem(..)
+                | clean::TyAssocTypeItem(..)
                 // check for trait impl
                 | clean::ImplItem(box clean::Impl { trait_: Some(_), .. })
         )
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 20d65d8cd9f..d9c277c047f 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_errors::emitter::Emitter;
+use rustc_errors::registry::Registry;
 use rustc_errors::translation::{Translate, to_fluent_args};
 use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle};
 use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
@@ -155,7 +156,7 @@ impl Translate for BufferEmitter {
 }
 
 impl Emitter for BufferEmitter {
-    fn emit_diagnostic(&mut self, diag: DiagInner) {
+    fn emit_diagnostic(&mut self, diag: DiagInner, _registry: &Registry) {
         let mut buffer = self.buffer.borrow_mut();
 
         let fluent_args = to_fluent_args(diag.args.iter());
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 980a9f7a47c..599671bd4d4 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir};
-use rustc_interface::interface;
 use rustc_macros::{Decodable, Encodable};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
@@ -275,7 +274,7 @@ pub(crate) fn run(
     tcx: TyCtxt<'_>,
     options: ScrapeExamplesOptions,
     bin_crate: bool,
-) -> interface::Result<()> {
+) {
     let inner = move || -> Result<(), String> {
         // Generates source files for examples
         renderopts.no_emit_shared = true;
@@ -329,8 +328,6 @@ pub(crate) fn run(
     if let Err(e) = inner() {
         tcx.dcx().fatal(e);
     }
-
-    Ok(())
 }
 
 // Note: the DiagCtxt must be passed in explicitly because sess isn't available while parsing
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 104d0d16c3c7c3fef2435fef6efb2d57b70fff7
+Subproject 1268e87bdbaed0693a9d782ccd5a21e2cab2de3
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index f553a78d766..84b33e3d860 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 36;
+pub const FORMAT_VERSION: u32 = 37;
 
 /// The root of the emitted JSON blob.
 ///
@@ -1238,6 +1238,22 @@ pub struct Static {
     ///
     /// It's not guaranteed that it'll match the actual source code for the initial value.
     pub expr: String,
+
+    /// Is the static `unsafe`?
+    ///
+    /// This is only true if it's in an `extern` block, and not explicity marked
+    /// as `safe`.
+    ///
+    /// ```rust
+    /// unsafe extern {
+    ///     static A: i32;      // unsafe
+    ///     safe static B: i32; // safe
+    /// }
+    ///
+    /// static C: i32 = 0;     // safe
+    /// static mut D: i32 = 0; // safe
+    /// ```
+    pub is_unsafe: bool,
 }
 
 /// A primitive type declaration. Declarations of this kind can only come from the core library.
diff --git a/src/stage0 b/src/stage0
index 57a01edb6fd..23ee3304b42 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,456 +14,456 @@ nightly_branch=master
 # All changes below this comment will be overridden the next time the
 # tool is executed.
             
-compiler_date=2024-10-16
+compiler_date=2024-11-27
 compiler_version=beta
-rustfmt_date=2024-10-16
+rustfmt_date=2024-11-27
 rustfmt_version=nightly
 
-dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.gz=24719797bf50fb494c61cf4711d6bb238ea9e789a1b10d957abb23f9849a06cd
-dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.xz=5eed456f0034e2b31ed4f6089163dd5e86ecb04630371e408aca741c32d845c5
-dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f337d992f4a730d39ae571d602f15d2c66ed0b6abf1b2c63112b570e855ac409
-dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d22b4f26ba8b82e32114311c1f0386d0126eecffa2accab8ca9ecd6a7aa38400
-dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=047735b5c90fca9f26e5eca2a1d24dcac6fdddfddcb89c9d1e2f6d0af0199946
-dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c70bce1fa2a6e98577683d94473ca7046e8add65b85792e9887fee4edb8bdcb7
-dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4c75417b640557b35172ea384fa34a3e8da1960efdf4a40cf8d1fdbdd50ee997
-dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.xz=f7f5e67b831af5fdb28266fadd7cfd9f092c066f7e7322b058d6fb2bc7f6ff77
-dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=5d94f4e51767b02ddcdafdcaba3404a3133d308fe98c7bf5145a41bde8146319
-dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=49166b4eb2e18e009ebde1e4c133adcacc3d5257fbd63b07418642d5c841957a
-dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=9e51ecc782cf9738adafd70c055ed793ab895c9616619c525cb52d7412cdf884
-dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=d60502f25273c2552997de281727b0f5914a2a97f32310f921ea714c5a1080d7
-dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=5796a33eda8d7b47c8982d3a2e425728cf681043151a291fea107b3aca9ff1a7
-dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=71fb2132822aa284cae878a76f9996092316942f84dc5a674fb8be17eb391cb0
-dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.gz=d089cdb87961d00e7dc51c767993342a2fa704756a94c421be7f195dfa6c5293
-dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.xz=42865105f308f7e0cf9af250b54086eaa20da8ef13e9cbf82380340a9db4ce90
-dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.gz=5753e00d74de3ceb1af0dc533496d7db6295d673eb05aea779734a519b5f789f
-dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.xz=dff93d0c39e8653f01248f0db05123018c63c92a1d3861935b12ad1818b00864
-dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.gz=4e2e06e503be7d15211dad18911ce951491d2596cef466ae8282af840184427c
-dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.xz=77d0d69f3e0c2b32bd1ccb73f12b5b770a1a720e7928859d454f42e611f77d67
-dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=5faa3516ecfe77f8fb21ba80e78c21a1b039f5fffae508cceffd04c8c329f152
-dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8f086e53b3abffd7c947f5b0784f9977ed4559e654805bc3877ada99072d38e4
-dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=2147f76d151c513aaef63cb2365bb2c9a8d0eb21a6b1c7c2ff535dab0882c46a
-dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=db2c17f1f3e0af9ad56982e1396a031df07939aa04c73795f541b16161fc3bdf
-dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e5d3fabc7902695ccf85171dd16cfe772a480dce203004da0853170450e57b1c
-dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=db2f03a41470e60a0070b4d96590ae049c23d2c0f8c07a5778023a4ecf3e52eb
-dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=49610d2df0b6ece6b2afc583db707eed0a6a12ef99a8ba0a82f9acb7c1e15fca
-dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=801a92eebf0c068c88a48129b054c4ecea143f38468ff5d53e28fd00a0fad6de
-dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=db8a9c4bc9313627d5ad2ed2ebe91b6129958254a32862aec67edee10cdf9bca
-dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fb2f2f2acb7516d98a6abf17e84e8b36beb7179c69776d69465f1c981466321d
-dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=87effe21c4b4333769fa7b4b0fc4bd43edaabc1c8ba33e75480cb4da0d59dae9
-dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=71701db843d0974b4fc09afb65e3872faaaf66bfda258c9627576efe8f998f96
-dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.gz=6485ed4c99deffdde4eee34e46b8be2eeb65a3f8f4b4eb032a4ccd9c6f4e29e7
-dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.xz=e8ee8b61386d490c8e59e0c2ccb30fb7758ea0ff0b1448d5f946d9fc58496a11
-dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.gz=23e36a4892e948a6dc231d15913562f1f95f798a62a38315a6b19244aaf78385
-dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.xz=2db43b3b599eab832a13c784d3a1bc60c3222f5bfce8e112688e1478837b8c25
-dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.gz=099c529cc84219ae3ed9a33dbc5265c46a01c8cffb8989e66e367078bc981eec
-dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.xz=efef4dd4a40d4f96d151293031783688c84b088a5f2cdde84d931bd44aee923a
-dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28633202a502121e9369e93a8cc66bcb52b2cc959d7598f9bbb8e4c840381baa
-dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.xz=c7b879d2e7d7c21eafc7b8e9f18f009d2d38f91a2eafa51d25d38e3b51e17ef3
-dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.gz=69bdb56ac4f47fa614fa9e8be5218a492d31a423454c192ed5850f49357687e5
-dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.xz=36c995c1dd55ab4501f250a77f27cce34330daa2a3e74129ce389aa23b4e3a05
-dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.gz=84bb641a5576ef0e93c7b5bae7417eae344f32271a0ebc31bb987d15316815a3
-dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.xz=a7311a345dddc9f8cf1eab6b3e82658fadb485bd755a115d4d6ffdfb42a5625e
-dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=9def7618829111d1014e21fb0bc10abc26459e59ce61fdac5fb3b63583f472c6
-dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=97d124a65a7d7e5610901521b565ff031313685cc37a1caf89de58d952065c3c
-dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.gz=101a440c383011cb4621825481582a81bfbad0ac03439542bd8d05ccb5aaf2c4
-dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.xz=4148b4311ce8e1cc5dae86d5f27e207496b85e5c23a53c7bc5b05ba18918f717
-dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.gz=25c5c35f2acd37a7c72eb8dc546cb6e9f62b3e76e1569d188bbe2aa9b31ea3e1
-dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.xz=9b84ce176d4015ed8f6946ef2d42f2f601cf419d1a6477f44bd6b7c7d27c95fc
-dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.gz=ebdf49b8d4fab00c7fb4d396c54caf5cb234389b7353856734b960f908c3cff9
-dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.xz=4d0d5fbc235d8cc78e9997302c45916008e203ba7f02edcd061290fb9639ee8f
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.gz=6693f5a06df0ea5929df18b633ad6373d098db4454d0e1d35e4c19b6dd7fa4ed
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.xz=351a1a2a13316161edcf97238d868cf4b1b5216bdf28ca0aff5a1dba2a1258f4
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=f0e13e1700a1cbc1489c0a5728ce6c0f5ba1432a75ca2c0c0573b9fcf130ae9b
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=825550e3a2afbe15130dcf7b702ea62b3b90f8a1e0b850cd6e9a5b5dd180e72d
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.gz=f77a6c24301c5c7165de3bf51b5b6d45e7d37a82d00446d1abbe5a5c591ca616
-dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.xz=5a9507e0c06b252196203b01319355e4d246eddead60993262bd680b6a1d2315
-dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.gz=eca36ae4253e5f1b51c065631a650135b71797b452a7fbf6dfa17c49a01f71d9
-dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.xz=1da17cca8397bedda8b5403ddcc9f7686d7ad207daa7389a6cf80f922bac8140
-dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a4eea434371a7d95b473410a42d8409995119c85954f94a75b8b0a69aa3095b
-dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=cea3d7d9568d2ed86ab11d28f5a02cf36210971b798c4d61e133357c24108f6f
-dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=355fa0988a68a1a331a2794a573cd065e6fbbe8b312e187dfff59f4f4245cc5f
-dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=c93347602b0133e0da072243ba9419c95179f9f548b6284612967d7b80a42144
-dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c4305667ed2a77764c729fe236491b239cea7c2605039c2bc28a926d21f343cc
-dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=02b6b621a1b3b91e25482400680cd38be806d7de541cf364d0ed181a92fdcbf5
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=830e1b90ea156eee05b0c5fab514d82558e2473eb5f6bddfeafa51e7417315c2
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c5910437177f607439a6b18bd05b93c3965f915a0d372fb540deecf044b21880
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=7a0f343b5fa50168a3edd0770dee148c82e43e7b2b82e2149ca22badeade3218
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=dc4d7b3cb830451044726e72b848e529e92ec0330e610f06b07f8ed37415c3cd
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8a9e341e6f208d5036e4c774f68b75802c64c53c4a9381ffd5a62e9b3c486cdd
-dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd24b56cc9891d9a1246e62eb33f6de8385acb265ca875af79f2593ff4bd323d
-dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.gz=51a58a9f663de787ca58da8e4ed705a1099bfeca945eaab3bbce01edd45aff4b
-dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.xz=47fcf0fcdabaddde929e4828c1de1db3986af1d32a752c057ec69aee9c8f6162
-dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=207281137a1b6ec8c1df21c581c23a6db7bfdd11c550749203bbe24b9ae80019
-dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=217625e68479d09d8e63f931983e030ea9f0829cdd559ba88bf657e711c96aa6
-dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.gz=4c5fa8fc4e18723c4522a1e93e9e343e35f02e74fc82e6fc44951bf7e1849371
-dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.xz=f4440f97ebab6a79d50683169994cef569a427cb1811b85ee196432d4e2d0b38
-dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.gz=ab7dfa2b8aff6bb7514798d11970e4c09c8a4844d7408e295c547f1a87c23ea0
-dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.xz=fb9ce70893a8c89bc3e66dd6ded2e0c4813c96bd0781b6c3b420a278c53ba4cd
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4650f832189a221337fc172c2ffa113ff209774949ae12e7ef159117a02e984e
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=f6bb5528b914311802fdb9816260e8a57531fedc5f68bef2dc6ba83d59d5ce4c
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2fff203abd959498321680582bb969de89c9de4718b38e06cc91a789d7fd415e
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=df5cadfd5895ee1552bbcfebc40b34826481932bdde309ecb2c13f55541ca2c0
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e29900d97e62c7568395191e1230fa6f98f971c1593303810f05d4db5c68592e
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=4455ff5a1de11281aca0df4f3f6d33d245314ce4276bda9d161bf850eda24ad6
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=26fcafd19aee4fcba45875d0f35aeceed7cb0a0fa070e6a2447b3d9b86170c8a
-dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=cc43780fa58e7fa1d23a3b5e2695dfd3f4ac3c02398756516c395f4546e2042d
-dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a67a25cdaa3fabdd2b619434e3b98f05acc13f25cc7ebf8f936e7f3d1761e272
-dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=e8ee762127e02a73614e636b77d34d927f34e967cadd79158ca6ea27687c679a
-dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.gz=7343489518ad6d354f9bfcbbc884d1c0e4fc88c4650cc68d9b9b84ee12b750b2
-dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.xz=eef35d9c016fdb67b9825104558ca0fc1aec3af8a738636a0f24797ad270b8e6
-dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.gz=ed36702bbf1d45c263b8b52a06f2b4a9783c6ec78db28e00d317acd09a549977
-dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.xz=e4fbf4007af9858e1bebffef6bdb4c66f419b035c8fb385dc70d46ce2e312e2e
-dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=1eebca6a4ed9b04a1cd3fc57f8f75bda14cc03c8909385586c8a084e46aa96fd
-dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=0bf68ccaa22a4782f23a34b8a52ca250b183e265f12bffde7cda9ddac515040c
-dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6f7b932bb0176fefbcc1de700a36da7c60dac609ec91e6bf351e4c42ea6fb119
-dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a0d9397caf812fa479da6b389b653fcff451f8d54fa0545e5c908e73391b6dee
-dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.gz=5be2ca5bd0340fa2e7ffe435081d1848ab883e46a9c0f07eee69f7dd9d08e0f6
-dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.xz=ed563b78d4201ce29ba79cf6ebf5a3b7d8020611309e39b8790c59edcdd05b29
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=53f7928406a1a14dfc6774fb2704bfa9c68091b135b750c5e46e3610e00e8c72
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d71cf98a8b6dfa2cc1682819d1bc5bbfe0eae819f63bb91d64e4f52bbee4158f
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f65eccc2a47e34d96faa94954c738813d9b5acae351936b07df6ee2ee8592296
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4f44230338a6b6bc17a8a2a80125ba18a9dedb6f9347c6e93b7f7b88c87e4468
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=80eae216bc5c3f77817d244f0d81cc13704894c1c7bde30c89b4f58b6049767f
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=b8036aee8615786593f83c3e7808eac2a59ad44ae9f5959b9719fd475b3197b0
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=95ca16bf6931261a62f4a3637495c02450d34fd0a0ee8abe350881b9aa0bc773
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=df92b9f5ec3ea09c2cc48e4c91d41ecb1fa82db87180458b1e051bbceeb4efc2
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=26a4426464874411bf51cf0148569c9a110681632d228dc9c9d57fbe24292e93
-dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=70ee4948185aec3b556c963ba030abbb6424e09190e31afb11d063bc2ba21664
-dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.gz=50c5b3d721cb5d83ab5f277c24eecbdbde32bdbc208bc0597830329fd19bf786
-dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.xz=9add40fc1a971f135796a8020e3ecbc6ccfa657714cee2535866f2af38fcde97
-dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.gz=d9e4695576a9f34e67804a636de6164fa7d381ac2193095cd2daa74fe148b748
-dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.xz=6592a61388b53c3d3040245b8634715026f1e2a020a118edaf43f98839537aa3
-dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.gz=da24db2c8642e8273ef7d0e74fd32a1045ec99f5201b35d0116ba1818ab330d3
-dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.xz=75574d203e5e15973ce1e6e12a43d6b26825844382ef76b05c4dd568912fd16b
-dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.gz=2e4bab4042bac836ac40e07c36c6057273d6bffaf97b1b22a64cd0876d48895d
-dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.xz=f335988ba2ae2853c4c8928562fa6ed81a2bbd2bd5d09dbcebd7e64cbc7d458e
-dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e96921c51d49ae28871286147d589bb59eec596826d1e0eeddd928f57ed4499f
-dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.xz=c17d7cbbc6bb30899a1a94f74f380bb54878b927ebe58b31592f7adb64d7b5fb
-dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.gz=f9030f5b2ae0411349f1f4fabd00efa3e1117ca5dc5ba60fe87f33f94e51787b
-dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.xz=d45b9c7c6f8de53f99b550a6d673bf8ff29e507c60ef63271d7d5ac73c765e07
-dist/2024-10-16/rust-std-beta-i686-linux-android.tar.gz=2a6b9c893d2d8bbdb5900c4105fe54a988101c7d69f504e4d2983ba7aaadbbd4
-dist/2024-10-16/rust-std-beta-i686-linux-android.tar.xz=94c884a0cd03fe092bdfb6fe718fd335921a82c9c2887e0e68a13fe6a183a877
-dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.gz=2d4a8b299987ab046536db276f3c4ea97413be5915189b9af085e4a4ba7b28ab
-dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.xz=eb60bf4d73fa45fe61730427287585939ff1a14efa8910877546818167b343cc
-dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=ec0f11f5cce47e6ad288393dafaa69b27fc5207194e886f0a00b4e6c3a006164
-dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=10a5c127538bc9b951c62692ca4d626cd669919d5bb2236ef6112da28db028a5
-dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.gz=7c9afcae592f5494ffd2baa95947b4fa5483c795e516852b463170e4797984cc
-dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.xz=ad9381999c1846c188d7264992c79faf413d675fdd70f22f25afcf84ed6e3b22
-dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.gz=9b4ea3de244aaf14b6759807444bb983ec5732b119faad1c9437eb2c02d407ed
-dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.xz=88f975eff5146af6ae548e2d7be8d402ca3d6f470b6760b75e27dedcac9f70fb
-dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.gz=8a8a255695d36a86ab32abe9f37f9f6f3e9b75eee75953486d82f186d8342180
-dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.xz=00a55b220767f3b692286bea728208bf665ea9a54869f82b31805b40ff56f763
-dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.gz=96e838064bfdace0fcd5596c50714585a221a5116e2825aba448cc1f188d0edf
-dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.xz=78c5be28afda04d536a634a049c175b38d46309eb4b02126ba2cda3102b92d45
-dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.gz=41a11092091b1f3b508f606978c0ac026e94614fe4b2207522b4f5f3d6c3262b
-dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.xz=a2250a5bb179549426ead55edaf3eba7626ee57a5e2c578057c3166348a47523
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=782998317c6c9cca107e84538ee166a37490b287efb437e5da9bf799178084b1
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=75b15b6d6db6f801a74419aa294b9537aa6e92b4d9d4c482e66aa6e319accee5
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=003a9949067435194f6a9bc6ea742876d5894ade67b5831c111826aa8ba5c2d5
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=5f1a4b6acfc1c82049c13ee2553ac20df016062feb368a54e44aead601105987
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.gz=f5e851d27f7017832de64c134727b7cd045495ed93fece21101c1e32b4c4c5e2
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.xz=289a56a0ee6087fbebed28a8d2110961c08889724d1a776a41094d5589cd112d
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=86cc3aa69dd4b18fc8435b6f6c1c73a24dc0b031cd79f942f6bc20a11f093f67
-dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e29c510424862fbd96cf61e89b6f9d64cef3c0274dea125f4af2c2a84816f5d
-dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=7506febb3ffaf1e763084d06a8dc9da096155c6a609a5c4c26feb993688f45f4
-dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=9c7e50509abfe5f0faa41eb526effa915e0799f59e5404e5a667c5f674a1ed18
-dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=6070daa8b4fc8bfb6c392767ac669a80067520c0fa85c923cb435c03a5ba6b9b
-dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=32e4064ed11bc521f26e222897ca651704e41bd42df214eb618b6fffcb909b56
-dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=51a092e812baf52f5eb7100e433fc1d5ac7cd984f8062b7d960711b9b88f1431
-dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=444bcbf145d1aff19d8e2474191ee4ff0be738c7c3b1ded12e1a9bb35d700c2f
-dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9a4968669cb034ebdd0623f57f86a674df513abf6c01cbffce0d104447f0aacf
-dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=11e478ed0cf115eaed256e9f0f64ab9f879ea0fb26b2f520a6388d3efe705422
-dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0476e97436699b50ce459b3c38b55425b81864162639997bc14bce33fd7ea429
-dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f76163c6963a7f1e29cc6a348b68e3c0659b739383273029eefac4d292280a3f
-dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f922ff15e927c047bed29d64534218d392bb584e12abdba09d9d9243613de3b4
-dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0131845949fe27479123189bca11f2ff13aa14e0349c0901407cf65723271fad
-dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a7898b83bf49203172e6191cc720b6b184aca6cdbe44386278fab0e6c8ca4bca
-dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d5a4a03dfa52f732af211ae3ed3220fd76c5a2a6babada0bf94de3817e71cca9
-dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=c074043d065a85860d2f99b657035b87a1ee7fdcea53c557035a8da6fbba96ad
-dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9a02c6c4c5cf7c57942a89da30869d7bbe2b0f5bf7374b7dec868bb5f84e00f6
-dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=1c016db6ffad0ecc552025777b2d2df5a54d6ec3a215eb2b4af0f1ccc6e45f14
-dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=399d56e3525aeb354a0c9250f070a43a7426e185960db6d8b57484f47ad11a4d
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=64f01a83583f4d025c95b3b2c09b86c4bae123c72a66a6a0995994d4226d34fa
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=794cb971242dedc2926a6b56badeffd1b4aa4f1753a22a1228eda8f336c2a5c5
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=1eaa20562af0921066ae04c8e1d9191ecfc4f9816a721ad2797c47b58a343084
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=423b35248c797ea494e6462b4a9c16e49649f0105b06b16c6137799a82f0a401
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=38a31b095b74cb4b678ecd797ed768f4f9f967a201b79f21b059ef8a39fbd4f9
-dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d7a53419a2f604102bda0d0b8ee9aba790082ccb0d63c31ff28be15f37ee87d6
-dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0cbccec64f57ca0951fe678299cf17a7aec8bb2a8d71aa7fea1a26cd720b38ca
-dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=aed7bcbb60aa5444ed8a8e1ccc7b74cc978b7e1646eb618a1899ebe61adf2c34
-dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0cd68dad85a5cc084d8a0cddc275cd5e932e50cea18d3d622d03ecca068008e4
-dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=0873ae093594ae2d93f19003ded34d1d6d4884757e0a5a790d4766be4bd7622a
-dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=ae70c9e9edd7d83776cdd0013e081d3b16dadb2a2504037b245acc82f104112f
-dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=810c1346632064535769e8fb15ac207de45f06700e8cc9875b3971c44725a3df
-dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.gz=0538ccf4739439c52d6c7d99b573e7d8163a834a6163720829816d291e067217
-dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.xz=8064bfdddb99ba6ff202ab92e3492bd2191ea11387b930a35fcde5ac7e341c29
-dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.gz=a988938091594f39015783e78a334d72d41f5a3646a3da09fe7a7a0db7ec2662
-dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.xz=0dbf287df801225c52d4dcbfd7afdfd5c1bb8410d9342885c092a4982a0d038b
-dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.gz=d5b46640810193ee163ef6cf3bb8d506b6844104c3d00c033d436d79ee790dcf
-dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.xz=f4e7ee83d5392e2496b9d3fc1e42b45d73be3b67e723a2e62f931c11a61480af
-dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.gz=0fa0ba0ca7c4e73f8b9ff2800919484cad7d902cc5e704e5aa3adb742cf6a6a0
-dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.xz=ce3f3f3bc51cf79449df550b8c3fbcac588444b3234f379b93076034be6a40e7
-dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b2aee46d16f38cf43cdd3f3fab78df181bab6438cb012c2caa56fa097ad1402
-dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.xz=3ee398b8497b7920f5d3cb18be2334ce440ec61b11e80c3ffb9eb1d898be45cc
-dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=26a67116e52dc1fcf179dd226fc28e3e21f2d2b482330d254b5882502573ee6b
-dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d051ae1bc98060db4a2ca7fa3c3dfc6c3107632631edac41d553e4b192ccc2d3
-dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=dc34a8335b1a9dc077e38b4e4a8222d84340de604a6af547fa17bb142cd0c4da
-dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=2d5c375d09bcaad6f983d4c4e0762532feb1d3706beacbf3a8d2e4fd75bf0c71
-dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=30c73a59d9138a542337fbb2be848a152172be272a25a1ad9a28f37510e35e94
-dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=467775974be97da92015790d49cb4f89d967ed1fd7846456b4b30e20f9585501
-dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=06db2989a00b1913822cec211225b0d37143dfe1e62d394c18c04954f7396ac0
-dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=65de9bf3cfc8ac6910953b2d3b2e9de532220f692519875e7da50a6493500fe5
-dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=26a6aec0f92b238c4d75c9eda3ecbb8bf0f1628ea5bdf52941e7b5ca398ec03a
-dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=7a4b72ba1d507f418b30d7a110eb5e9025872e2398f0aa68abbef150f4c49ef1
-dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cf04dc8f1df723dbca4fa3a1155dc3bced6b3c96588bf41f6bcc196b74ae19cf
-dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fd17a62d10d27c13818cc3dbe1c62aa85d9c7123b88310d12cc40939010ec97
-dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.gz=64ddae5e3e08ede16960f50595c4205de9962e0f5b8de9de5df1e9a8946bf66a
-dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.xz=0d6449807c02e1ef817fa2d378e77d9becd3a1560192bc9fdfad84cdee5cc8b3
-dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.gz=c4ba753891162f604effac480ded4c536f294e39768f41d7b4fea1ab28c71be3
-dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.xz=46a6f680f19ee2ddeb41e7aa13bb91a893ae27ae89ec41c36094f6e4db4a3e0d
-dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.gz=3f89ca539044a79abd2b25f12d08ae954a7fcdcdf0288239c57d241b225776f9
-dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.xz=18a922eb41f5c907bfb624d18ca882dfd569f6775105dcdc29e7c7eb49187859
-dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.gz=6dec5910a96e7a8e0713c109c993df44094e03fc8ac90b1a99f72dfdf84798f7
-dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.xz=00e21ba70b0ee2760dcd51bf68f6be74c5cf38fc301476f406bf1f1d21ae7503
-dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.gz=c0b620ffb0debcd0f20155b1be250627450f14b4f62b32d9d9e4ee4c4e57cca7
-dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.xz=4d14c5de2f92b67c99e6fd2342d4ee968805d9eb68d4f9d1f549bb27e866f3b0
-dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.gz=b3ffba3cdef26174462e65847414458eba1c6aea63a78f6087497a04b427295b
-dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.xz=1923ee9008ca30677642d1e66463555ba6fcee88dc0ed947e0ece7e4ce4efdd4
-dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.gz=e8f1cd196c5e3b10a58f640cc8bdf3d015e1b23d49724112aaa7e4019cf01107
-dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.xz=5fec3b22adc67fc6e4ef2cb873d446cb1520cfcee2ef4248e3dcc2816ada683e
-dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=852e5067d47ac896c18e424cedcb984b0b4724b7fcd05e550151de2781603737
-dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=2333f02b870c6e7b673f5e8e166bf9166c3f6d1586daafa4eeb626d8de5b305e
-dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=5c2bfde266aefa83ef9e65448900f4aa73e1d91de3719ada2512230a69090e2c
-dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=218f4a4861812e38992bf261e390e95fbe67402f89827e6ac1b68fa42c705166
-dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.gz=5cd9859a22f77dffae58fb6573a8f5e23dc75bf030f54c152714777e5a01eef3
-dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.xz=be754bee393794ac427718b687f5e4aaf61aa1544795ed0da0b9d20e77e45803
-dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.gz=556f48c0ee8276bc847f3519dc0dfb72bd11cf27add709815da47f5cbb48716d
-dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.xz=aa185610d66b606913d1102f62b62c5bbf9c5baf2e091d14d37c30b1526fb583
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=1a7dd15c91fb1597593b27dc0b72bc0b1a6e758935efae3c9db714cd624d7639
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=be18c0a1f2d0a1852c81ac1619a01d04d0c8c22472655710f643d86cb559508d
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e18f210cfe890af8285da5f99cc476770daa78cddb7f8213f7f26f66111e17ef
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=b207877400dbfad09b6a3c2917516b63faa159f922ad03911736634ff46898d1
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6f277d2e2e9a9057e2a2c8045c3949ab36ee8ed58b64829b10470e0c6b111671
-dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=51a102726ddf492dbc530437047fcb4d5e542dc4ace0e64da21c7ec79ebc001c
-dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eeb6a46dd78fe3b477454c256ba8486b906e7a7ed044e686bd4f8c868265bd90
-dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.xz=67e103b9742ebf2798fe8e2647a6755a1d253301fea13a5193ced5bc394b9a0c
-dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b42fcd18458cff0ffa0902a0797e9b42cdf9475f5e84279972e4010608a14ba3
-dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=878e3950e0aefbd5c5c155f1ba2a4e8abebab10e3e77311403fc2c475e6da9df
-dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.gz=d72be5ca5fde3ac33da483058b8132707c93647652245864c988158e6dd70ca1
-dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.xz=270959bb47366b7276717b677c5303ba0d579c9fd1f98fcf3774ce033caf0015
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=33370d376f3ecd80ddb5f614eef222c601e2df5dd18ae98ec034922790f56218
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=061a262fe98e6e1b41df6f9f60367259d44215f528938574098ede8698985c94
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=70328a15c8e29be07f248bb073336f06eba613c377ea4e98a1e0a4abe5e2eb6e
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=ac389ebe5ca69cb382fd104161c9068bd8aa4d28960d578f2d925faafffb61da
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=22d350bc0718b999d88e715cba73ef1860e1b1b8efac026f46d9050952d739b3
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=0761b9cb94210ee40fd0dbde38cd049a9e727a73da4ebc2cf10e5db92e6860de
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=35f975847adac17d19abba5385b951ce2015dd8b62ce4b0a716ac612808cc9d7
-dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=5a9679805c1bdfa835aee94ed0d3ed4d2b4d0b6a8e2ec4471fcbcefd331cb200
-dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.gz=e4269be360d9823bccf6f7d71e4f51feeb8e955c7851d5bb6527055d709b68b7
-dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.xz=58880cc63fb93bbbb78fa4268eb69b37464b429de2f007abf05f5fd7c53aec8a
-dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.gz=42c77c14c433f43a092bef5ea0cfa60aea747301a9499c66bdd81d7998a74143
-dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.xz=0cdfb3cf58d8f6db3bd65f4848aec8a431ffb4e1a5f79e56ceafe09849a96ac3
-dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.gz=35ba471138c115ac3e1ac3560fe8590038cb6002d22a45dd92f09a868270d223
-dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.xz=f250b60b52e2f84864406a0ef7e2f8896e1373f4f14f555a47a2019fd370f553
-dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.gz=7332cbab92c48611604eb13ac025b845fd0dc0bfe838a4edb02f8266a5245aeb
-dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.xz=7cbef4955ee702d845116c59742194b1019d67f564145cf809ecec67245ca8af
-dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.gz=59321dd2f962c7b14514fdf1ec96907c16735a03a799479055f40f17883b8b6e
-dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.xz=336c7dff9f3a1d9de819a32f62eb518dd94d45ee591afb01d329127a2146c3fb
-dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.gz=00c53e3a327909882282a32850c82e4aa18508a5e355532951d380e985b75c79
-dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.xz=39d09b49740b0512a84fd5351d473c5802de30721f621cf99ccd0178d8eebd60
-dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=dcb522627c49811d2e6eb133725e301089a4942da1347721ea28f2cdd670685a
-dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b9ce402bb130d35e482ee360f8f142726ff51bac3954aeed14800eef0bd96f6d
-dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.gz=670c0b78cd5c985e6bacb2bb2cc3a5a2478c2623992c4cc35d0d4c624e1b4b16
-dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8a936c0c457a1d5c659611e7a69fe9934313d9ceea04c0a0eb393e28544ce7b1
-dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=10150caa2130a73443942f1dde7c849172b57b7b9e07e8939cd6c126c701d7d7
-dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4dc0ffb898e66661a1b9844b965a0b0ca115bd6d9bb25fd5c5df022fdbeb56bf
-dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6db24d0a3eb7de6e3d40dceccf6a92ed86e170e0c4dd2ebc9702652655ad664b
-dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=c5699a6a4ad49c34a77c94a4982b1a0ea7f6dea84d2771c24fdc05dfe9d4cdb4
-dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=f5621b39e7608e8461b559f3c3e57969e7eadce82798b395ba41e6302b2e0283
-dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=d7f62c0ac375f56d9ebbd0edbfaee4684d7d47ed8ad38bf7d25fb75a5770bdb1
-dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.gz=b895fa9240c3a6c089cde6b08a21408b5a6f38818c4a9cf25394b17e9610da96
-dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.xz=e26de92566339b932cdf4a4ee90464f1f3863d89534c03a3c9f9a632a278993d
-dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.gz=ba64512c0732f5821ac4d1eb7fb53c0f340847c0cbc7dd5f88f67e03bc3f58ee
-dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.xz=cf9872ad8ce5621faf517c2796620f24c1a99bccff7f328b7e7650e89e604b22
-dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.gz=23496080baad6b976f8680b7f6c856461a410a4dce5c66a41cfa220d9479cd95
-dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.xz=9799594bddbe1e04e1d625a6ead04efdd4749d4f0773585d21ba2be6636f0bee
-dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=5a1b95969f002c25717751337951aed39e6f6256ee58acce150d5ffaf0046300
-dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=36bab05ec8b39c7e230ed78f64b2680ea21fa9f7997c980c22edde61c0799b5a
-dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=19bfbd70b98c0bbbf29a0a796572d1661b8902132087173ca0e6aaadb4d51d09
-dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=629e42e188447a392bfc7cef5fe04c31380ee30523dc0bc33b0f3c02bd2fd82c
-dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=5d8b1daa253ebe0750e6f073b8367b053de09b4f209327d4114bfa60b2bb5602
-dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=545d7ad3b7b0b5d2ec0b4bb70b7e31dd823048d6087d6c3fa2139f307ea35fbb
-dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2111cbc7586a1e58dc7e6e54a63157f9606f5586c7bb72ffa15f1a94284d4c97
-dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=0d6702d3ec5a6aa9dfb06d565e4e16b27cd3d445871bf2344c876d7ffe2f8a32
-dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0f750831b518b452a2ac17c9bab3a02f30f58bba6ffcd962eed06012102c7b31
-dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6d476e16109e9bc5dd055c537a9382ce154d2837a32bc2c165a1aec76ba1ba43
-dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=850bbca95670afa1262b5d46bb02f0bb367c83f851bc2a9817f8bf2eda9bd2ef
-dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f42b3b5cb506886bcfc92c0a7f3dd3d0668bdda0f2db657b98becb4c0e99bfd1
-dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f3a8541b3e6c12f350fcfbf43a8efb2a8bb48a62e055d9dc522d568b94476f43
-dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.xz=12c5411791c715562c99dd211095c9924142053d510e17e6ec50b7b8b927eda1
-dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.gz=95885bfcf5fc1de80d0f9b5415dd261136d5577b7d61716c184a6c6379acca21
-dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.xz=881c9d88bf2a848f5b5cd61d18068e2dda3542a65e93ab373e3a047cc30369d2
-dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.gz=c04ca1768c5925d5c7e19d5f232adbda355469974b19a2a130a6967db94b56c3
-dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc02593e98f5393ce2032fb605ec2bc053a1a19311a5a80d27c3a552ec8b968b
-dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8ffb930c33ad454806f2f61a10949a3fa5b92b9313454927dbd76928955ed7f2
-dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.xz=ef0bbe8512b3dc9bdc9f3a47abf2834bcde1fd7f59e319f7c7040b7100ba1f8a
-dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.gz=eb21f7739dbd7c120dc9552360e8aa6e1e0eee14d80ea16e3dcecb9e94efe7c0
-dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.xz=9e287f3d0c7e402dbc121cd737fd2360dfcd97fa886770aae93c07474494bb77
-dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.gz=1cb86b6953ec99e95d92d61ead263021d16921cfe6152b6331efb838c46be85c
-dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.xz=c356e671ca97dcb4d945567e33f06911d5269fdebc19fe83a9313f574d446576
-dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=7613e679837e2769b9e8df5b8785fdb7e51665379e64547bae9d6015eb8e45c0
-dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=39ae7207f84ee3da16ee11271070e8b82d2991cde29771d5154bb2957d9beccc
-dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4dfaa69f4377bb724eb7d1990aea7ac219a960b690601769f8e06b72f59f86b4
-dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.xz=4cf72f3f0048e8cfb2b05566cbc1d76e9730cf1f71f9d0f3a71bd9379f30b08c
-dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.gz=e1d3ff748dcf1777bc2d999ec82f0b8a67295f91a9cb07a9c1123cd5424928c3
-dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.xz=7e21e89e218118d536d489d16e77e667df7ba7c809135ba179e7097a2243df5d
-dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.gz=244ed83cac923e00647cdd3aab9d0479cf420991e9e06eee5ffd8acc9e5a199e
-dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.xz=6dd93a671fca0efb2d3b8cc461aba66483624327a382fd714a526832034c8438
-dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.gz=56710fa9c7d46fb881903e08e407c258e3ffc75ce3de0226dcdc3709dc59180e
-dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.xz=6ee782709786c310fb1e887cc576e7e61b0a4b120f6a46c7dea1e2f2bf7dad1d
-dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=06f0ee2195349921d1ae791fa1628fceaa7adb377968fa09dbe17aa77c762a47
-dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=6e792e91db8b54e0cfb9eaed8187b5202ac5d5735ed0f73080a6a73bf15ce683
-dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bde52962b121472cd1b755c506b9362ff88ec582cb3fe9d307948c51f4d96f1c
-dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.xz=70a06d5b8175d078bd246adf45f3058d362f0b128f1dc11d3797840b28692bf5
-dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ab8b54d8436dbc6af279a048d2b75eea9eabfa369f23c51fc1c47388f642a755
-dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a2715009144defc9aea3ff0d6a15485d8feedd37b333658470d479600fe87ffd
-dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a1863b47208051a231f9571bdac3628d8afdfca7eac3b1cb7a04a843c176ae80
-dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=a5926e8e3e2867a8fa87db77dc26bd18734f84a4a685374dda07d50d21068f62
-dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f70eabd386aac93c676485bd42845e62b34c034b8710bf0db24a440c03b15bce
-dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cfde41ebe7398d0858bf507b9322c5f4959becd5a3a4624027b4bf3321730a29
-dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.gz=3d988126d6a0ed9133b73b8aea3b16d6355db8ad83254a7499f7dc3b414d62f8
-dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.xz=6efe88aab2daa0c7df17bbb449c2b815e085ca7e859b17bb578978d18ca2ea04
-dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.gz=2c2eb32ebe3ec89a985c07ce87cc1dbc627f5f8588aeac72fd381c6e19034095
-dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.xz=fe2d2ae70e0ce102794450d4259b706d3bda2c5b05bd21a863b2ecd8ed54274b
-dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.gz=0d633381b174f04523f13cc574e79af5041a231aa61b0befc406c7e3ccb0ebf3
-dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.xz=029558aecdd4862dc74ce9726a462f1d34a7e2a6eda5bf791995dfd6933096e7
-dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=2bdaa7f730f30db62ed0661f135227c54249786a78a8022428ead03766c9e29b
-dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=2a4f5982eac9cb5e8372d35c13a7832d532a31e5c38d13b0643d16832e1e341e
-dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a9a1fc5b74e19a567c45ce1789c7bfd50b28774bca8320886108e4a18a1d7765
-dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9e957652f80b2de14c5a8f5faaa5662d0ebd26e18b2bc5d248587d72413e483b
-dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a9fa9caea0f784ed096b3ff204a8261126102e05456c52d544c7036f9ee30c41
-dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0e3d3472e3e73b02aca8797ecaa2471e472d361b0c44126e4bfc2d25a8fad96c
-dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=211c52eed69942aed1e6b1fb4799232ea4fd3f898a44a4bb6343336e89dfec74
-dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=8c07b34223e465e17094b7e20efdbf8ec6ef5aa042485d3cfbc6ef58dbca0be9
-dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fc3cc6e81ef118eada3c01fc3535dfc622b92377d8e735f80d7661b4b847fb
-dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e885c534589fac79046bb31b92aefe7674dee13c8df1a456e91ca63e9d92c6d5
-dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=fcfbf29d105ade4a6d7537dc44d01c6de2de70d066afd8ac3af58bf3bcb6f7d0
-dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a5425df8cd724fd992de26434090e157e9d148d063161bfb43789d6b4234ad02
-dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ab96fc1c538a9a526124bc2cf3e97edd655f29f8d6d310b3b5f017cfbe6311e3
-dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.xz=096de4e9f80f40a294dfd1ba32e9de038c3449b2760189a5c9e46cf8e36dc0d6
-dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.gz=5614651ef2acd5ce1d43cc2504d353e471d9c8c425c16e3649f81e1cef44b86f
-dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.xz=26e39442af2251c52bcd275c7ae25a88211ec2f582bbe7a29724f816768c9781
-dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b2626513cbcd9b1456dce8543c2b11458eb052434f9ca84a6e926a77e5be2362
-dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.xz=87403c11e1b92bbbc2651183b2b480c41d9c7e0fa6f08551702c6ab308fbbf5e
-dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.gz=929029e67d34bc813061c524490b8f0030d31097fc1fd439acd4d8c3545589a1
-dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1584df60f086c6af01f06023236f612bf59be9d5b991bd09ed66f4c505737533
-dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.gz=d5ee8cfefbf164d33529f1a777437f49216e93173a2ac04b605e74fea89fc6a3
-dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.xz=9469aead14fc03ebe984e51bbee0db6d1cd8e877b67ca361c44939e2464a95fe
-dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.gz=79bd918b2a391cbeb885b7075b1e0534054c81784c332a2aa8539d0e1cd15f69
-dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.xz=16b808026a4fdfaa85a4ac01b01b4fc79c4824a651bd4e412e4ee9b0011eca4c
-dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=62224af7a1831140fc3f06e7e918191e9443751549ec5c96afdcb3ffb5b18e06
-dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=78bab115fa696fc95d911655575032fc9af324c8b6df136044f11681239e5c41
-dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1a76ea2b1596acd396585d78d01be5d3b795641d7b20f84379cd2c344e7536e9
-dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.xz=63ac980b41b0a3b744d94727af6ee1679b8bc4c50db4ef68402d0253b1852ffb
-dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.gz=eba61354aecfea64815a68b569122e029501d85876d37f5ea4119f36f932e146
-dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.xz=37f9395e78a2bf2977b38929b9511e9668f26e23705d025609f028b282aeaee2
-dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.gz=05cc308cd0c35063b43a45dab3e84001e2d580b10431c74899a86cd8971e5b36
-dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.xz=aede50889786bc1e902162b9347cf59ee67b15e902b0ed78d7187d3c24a7c4a0
-dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=1c25ee283dbc720b471d435ed952e6d794ecacafd4c889a2ad8d43725cba8ded
-dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=67602978481a53b0b4681523d94bf79ad731a369cc088c3b0adf8e7d54b1fbce
-dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ed7c9c38071f9d1e632104ff1d9a9407efec99d74eabd127db795c56e84b9d73
-dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=65ee60bfefa1334cece9f5da72789d90b4b5918e7afea2b47aa4d1450d9a1237
-dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=e92d5ddf80c94bdc34697bec4d7a1b1ea677e5fc6c68c41059a7829e53e95505
-dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2f1737178817318d1543deabd865aa83a1f395a36cc83e3717157b4dad827f22
-dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=a4be0eb92a011ed940db67973d5fb62c4b5d3fdd52a08981223c5fa5278826b5
-dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=a47b2dab4f20f53e6c29fbce06383144a67ece61a63f33c3fb86beaabfe4bce5
-dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7bfef0a8b7cb4a905ad145311c320a8ccb2048e806ef68688a1423009770b35a
-dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=d944161b92bdd74f3ba533b94b67a3a361a01b82fa5c156710608f00c46913ec
-dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=46a46ad32e2829550e301a84212f057faf21bf67ff6862f77f11cb0e13f80453
-dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d917336a949ad5a5f0fcfe1ef261d87d4dcbde22b467258543c50715a9041d64
-dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=38a9cd401774ff1d832e536ed0aca9a3f0d5593814bd6db9ba4f8341a5545fd3
-dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=fa2194663d11d517bbd67c157fc40cf67149246c391e9b8adf0a46c2eb96c860
-dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c5271c244d8055401d3d3a97873064b93915dbcc52108cb9b61381af1ebe99ad
-dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=56c6a0cedf3ec4667d65a209477cfe0d395e534654b49e28efbd3836e8a0dae7
-dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c4325b80bfc63dc58c4632ede188efdc94aa4cad49abfa4e57d81faad673a35c
-dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=35b4fba91cad3bf9e627d59baf1f1864e30d002b05696c61498e73fd0e0f299f
-dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=b2f856cc81be2c6f2c4250ec88cbab0a51c3d59e73fefd66cae9b1a91a32b0bb
-dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=1b1a40377a8a13b74f62f5bb382cb8056930c543b97261d32613c53826c758da
-dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=98b1f0fc4f45eae47a6cae7e7d4d9734979d8f860c7c96da281fa1d9ed3ca39f
-dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=bae7dbd1342d5aa89c335f1dcdac0d93f5cd8198ce9f869ef4c32dba8bc6c0d7
-dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=cb5dc166002aba8a95f7e10d2d9e93a66d51483540c7e733b528bfccdbc74d9f
-dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=c070a48d0aad7ce42cfe5eba9477a0f54a9e04c9ec5c770e91bd2db55d0d764a
-dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=424c0d9a047ac228cfed286d0a2936b857e1c575ddebd931ca634e0501c125da
-dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=b067b3d095a5b53191ff148d0e89baed0b53c2099142d885961220548b904c52
-dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=01acab58a327ee34d100e67a4a40a9efb66a64d478d6bcaaf94ce35874296c42
-dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c1a715f7502ef54a236d4ebe15488ec4c1c5cc5b1c50eea416a5b9c57de66f53
-dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=cb014573a52f2d6776e47f3f728ae1e8b05feac2274c5916b1545675e658fc15
-dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=5abf6bf36bcb57c0492e9bb4953ef78a61acf347d20ab788b4b31da44ae3bd39
-dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=0bee2c4ea3f8ba07c189f7e2e0df1b2627b7bb638823fde2839d46a353e0480a
-dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=df352612d69dff13b59da185581a48062e54ee07161b1fe205b92d0687a4e896
-dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b7b44f5fb37fac58a83c2220a68c251513fcca96c51a71b189152a78cf095cf9
-dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.xz=f5876f1d8181880e4ecb71eaa2477b0431dd0bbb45e6a4da8f20bc31426cb43d
-dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=cae33e30d7b2e5589a6fe681345f6edbf406aa803d0d521ea182a575ee32dca2
-dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=21324d7c6949bd12c841db8904d9485dd709f8c324e7aea31f2a9eb2a32844c0
-dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=cfccffb90721492cc79212ba49dd88361c6d38eab24ca4fbfd8110c2eefea001
-dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=05c528e683c40467ed3911ec5f852914e117fd71e8a0826f17d91295d4f1b047
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=97cd5e773bfebd3e1d78dc3d486a75b969e30f1dd0311d07c337440d275d0443
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=19989c6e9ce4d67e068d449b92dfedd8e07bd1a287cee0410f43aa43432346f9
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c3d8ed4650b4f7902a8643bfee849926892aea2e664400b858f61000966042cd
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=6b0dce2bb77036d154d15ffb2495480ed8c8cc441dc8979b4fd767af80e0736d
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=de7b427a783d588a778a2301a1bf8e4fec076ede2006e275f45d82a87e965feb
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=43fdb72c7e74c86eedbb01631ec357c2cf469512c0c591d15f35f747bcfbbd30
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3fccaaf7106f47302eb3c489dd722a91727e25351278a17f81d06fbb4cd4041d
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=988d6c342a4561790d1024455be643e17525ae07e02fe5238fc61d00c91d3cd6
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=71c10377a84b3bd612a83cd2822bc6c0eb4a540c681114d63be368da84ef3766
-dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1e6a3c7080334663ef6fe246eae3482a05446b83c8a0c659084ca8186b9cab01
-dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.gz=e68c96b5d6fc204944cd1bfd80e2c6a8332dedede98a968e170fa657e012ec1f
-dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.xz=9f7138fecf991a17483e0359c7a5a0b4292cffeafdd4b52b7c1021cbf993ec5c
-dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0f31c36e6b6b765e9814dd193861e2ae2a176160f22aaff6211a6da3efbc1fd0
-dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ab4cbc70a6002bdba2955fbbdd99f03d3e54d14d32bd2f7250be6a323f39dfd9
-dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=e088594f42b88494401df68cc60b8d94a4c1199e3549aa6dffd513b0c5f7508a
-dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a204d11814dfb6a3283ed84abf8b88492283eb6cfbec018a0f249d496e2db5f1
-dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=802ae62e1023c460739670a12b8a331637cec02aec14769bf0bbdbad44217555
-dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9ab24e33a80a442a540720377855710c2b33617531daa625dff537d1251bb9b4
-dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=08a139d7e1ad8559d3add81416581984d24eb997f5d03f2ea85a76eac62df57e
-dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=dc9dface28b81a1b241a6ad034cd910221866cff7188d94929bd80e3d2dc1598
-dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=ecfb3225d805cb7faeb185e43471b35decc735c1330bcb45d54cbb93fac0db4f
-dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=60437f2b7cd51cebff36687bc904c7493ef834e39033c08e35883b3de03ed15f
-dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=aab495b49ad218fbaf6f36e0dc82ae76dd867ca77411568f15039e494154d890
-dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=51648f6d14e8684c3f258ede3e97371c1530be584b5bc47a92b7bce84d70b397
-dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.gz=6bf818c20105a30461336053b40b9b298388b341766536137a3fd6039e7885ad
-dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.xz=60346687b8359a3df7bc4d7beb5532be716bb699fe8aec76664b5b5b4d7cacfc
-dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.gz=48b542959792f1cb4c316ee417fec68ccab0ee76a68accbe667fc56ca9d5a367
-dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.xz=b83ebe192f8e2d82fdb0765952e69e4234f11fd6a0a4a69d089b2df42a3c637f
-dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.gz=03b36beaf28462424b3b70e6a944d24a22a551c4fd9c245cfd5eef464047ec30
-dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e00e81bfca624087f97ae2ff675adf08a72519240e31cfaf0f4da238d7be8050
-dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f71e27157be06043624ebb769cffc92593d4db6d2a9edabec6815d0f9be64b9f
-dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=5bd77608b891be20b38739d2b1cd4319feeb13f92214e550a01c599349fd6ce2
-dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=0cda1b3a287843431991468cf8dea7a34221d42153e9421ed89a8f58d048e01b
-dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=57f3a4d73a40ffe0dad530334f2e584c1279ce3b81458023f034bf8c35dc6641
-dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=5d7c5164b12ad921f1d8461d0edeb17566bf4d5861d6b0f18f66ac1a91b7306d
-dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=8ba849b777182977ad9b87c002bff49ff9ad2007932abab98509e96274b9c7d9
-dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=03c12e5d01a6f0b66dfd728610fc0df2f3bef8d5cf418a4d5a385b11f35ecd81
-dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=db0b2d5a9a12c9c8aa0d5d3a320ef8f815ea2ac84718e1bbe94514e7480db6b5
-dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2e3a85da6e7a74b079a5bbbbcd433e0271b89b873aec22c19537669bd908a98c
-dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2b19af7ec21a9e442975b073455e4b3a2711832f6f4a521335034f47dd7725e3
-dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=c293489afe56e4ab984bab7c0ea8db292464b1b0a83b3efac3d38079f71303b2
-dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fad8d9fce164461c81c5fca56c3557e76635f70ad755cfdb1a448faf161a6b02
-dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1a4d7fb7e5d74649270e79fcdd5b7686bf3db6985d3a781ebb1f069404639884
-dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb1ca19ca8a99b68a1665937c2bfde2a275ff2746cd8b50e097202352a0f7cba
-dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.gz=32d6c59ee1bb8d1449393b37ae9399d24ecbfcaa6dc5831ad2bdfb3a586c8ab9
-dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.xz=5a9237c1b359da2c6aac0d6c9202f527d5982310477c414c3c03c6eee50feaf3
-dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9b03ad10b3e5de01a813fd9be676135de072de0d3fe6db63e82ff881b9d81c51
-dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=1e7b91da95fa7fba74c4f8937fc9e02b592c4a66260aab1a4feca24e136501e3
-dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=59efe9285d460cf8080d3aaed31742cc7ae5dffebb9bdd3410be22a061fa8dc0
-dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e64edab835454e2024081b9c447798075cc2df3703a8b627d9661c32233c8540
-dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c1ceabe8ad4f89b401a72a6a02843a5f31267cb9762d1a8c30dbcb51c1967488
-dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.xz=456708749343846153490593eebc55d78ae347d0a1096d0fdbea19c99aa24d9e
-dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.gz=e01be583da5371501755ca0f6d44cd2abef40543d7d97448933e27ba0de78c8e
-dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.xz=42dca4d9e7d76109a3c963b5783554d6ce0171001d744f3fa6b5001bc6ad66a1
-dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4464cc28f6a15d5a2a1de098f28224848d0b91779bb70ace3106f3a6208d25dd
-dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=5f9b9cf42730255c27bef5187241736693b5e39de9fde935da25c9f33deb4325
-dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d6c2b41d4fff28d12b254d3cdab480ac4a81054e50794b6cfb7ed30065cad5a1
-dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1acfe2f78ff7aa747e5b307b40ff5a8be5e8076897b78b2fb5828d1bb1d74cf1
-dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.gz=9d5bfab5bfb9e6d627a5acd1f54fb164538e84c449aa3ea15841636257ec7ab4
-dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dddd1663a821d99ea19864435e1c7daed6bcb4fd914e6b79c94d644836bc8d1a
\ No newline at end of file
+dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.gz=58e2ba5f6a388a5bc9ecfa1c7ec4ba3efd9662e1875ea5fba484c75c5f930227
+dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.xz=95f3ed14a6e3093cdee83f80227c7966783fffcc0ff0be6ef095df0dc744b9f8
+dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz=687b58e25baa685be9357048cc1e0c469c25dc6530db55e0179234615ff4d289
+dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz=694e2405efb25c53575599ad6573d8c4646a168e5d4bde922ef5e7d43f3e530c
+dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=4b42d00e701f90c1fff9a692f1bc1da957fcadbd1813c3066dc1f1990bceadcc
+dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=4f83a8cced878c03aea2d6cec7e1d588c2b6590850664f28f3b49a3be3a8b827
+dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz=bae97ca3778fbaa40f6db4da4f6da0b2bb870e9880165fc3126363f55a1fb23a
+dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3e617e866a8c03fef243dede8c086d085a6564aeeb5570bada62db5a16e95f2a
+dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=96d2f23814db8286de9ffce7bab033aa4dc656f83aa39418c8f877a5befbb100
+dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0433a866c4d8a434990746216232759345d3ef556b0b92358b231fc1e727962e
+dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=6a776c6eb2b7b4992eed6a127d11b8845695cdc5d23938ced2267f88f8d97033
+dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=2649e0f522755dcd511a6459258c3c3a24808fc49d3513f3d9098b17bd0f2c79
+dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=02a65e970ee930b46c2d10e1eb3d2e6f2420e08bbef039f10a8311baf57f274f
+dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=3843610c7ecf98948a5f78a364c223d520a084bc8c49ec0c3c8ec48bad6c0bf8
+dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.gz=75288ca1e65157b8902195ec2fff31015017c90d3b8f51890f2f851529b200cb
+dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.xz=5c694e50b41cd6f2c7b59b891eda3e728a1a2c56617b96c9da001b35885637b4
+dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.gz=6d1a66c090322ccf272a425c779f9165398e6bd9e0c7e5d0a5f262086d43ed88
+dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.xz=e826fe8be287f8969d11f620da9d01ea0d913eba145fb79ae86bc78674f1b919
+dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.gz=31e0d9a1ff97d92c391cc913fd865a0c8afd614279654350d469bdf881a1b1a3
+dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.xz=3b11a6be4863cb6ad420b66558b7745431834d1fac5dbda899a384dc30b526cf
+dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=59d96cd092a56d12ea796b65225479803edadbdcb483effdfa36e191f73483f1
+dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=0714a469cbd7d96118e9260f80fedf34b21234776904e9c8ec5b71c9493dd36a
+dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=25113ca9719a036ae581f68df4dda74f1446b49ababe7bb194510fbd1b296e7a
+dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=25bd910ea722fe2d4a1e66089352c92f97759ec7212af2b9a04431b469ed8e12
+dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=7a83c9f63d88849c4d691ad1d7fbe7ab5924b5a7d76378ddff5024269be95310
+dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=fbbb11b4c986186d94b0e00ebc70400d0071efc2ba3b802abdd877d86b8cacdd
+dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=6223dff24490e3e8506dfbe2b12620155d7c05fce92191cb01f3b28e269bf1be
+dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=6fb1edea73bcb76d9cb6061d1aba15ee4655a212c1bf96328a225c7c05df3462
+dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=0b7bc9ec0c40a6203fb62eb71fb6eeab43a4f64a2f7d0d51a1e0d041a216adb1
+dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=d77a49acbf26b8c9a2a5f79fdc640feb1c81b9fa38f442b81f69127f49c7cde7
+dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=bdf45a37fad10df4822690ea73840b38ee3e1048878982e625efbad3b2054f28
+dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=ad6a2f03b2e27711e1ec4eb75502782c4bc0200cfaca2b5246e0bd5b86bf29ad
+dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz=b0cc3024a717d33775dbea63e83f317f8826e564ceb4ecb7a6cf23676f66ccdc
+dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz=9d5b44a82803d5de5355ffced6ec1dcb9860950910bba6dc54878ad4da7ff444
+dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.gz=c7174c35b530453182f5f0b15c6684c030a2ff2770f4cc1a4a4ba75695e53b99
+dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.xz=c68c26159a3fb4d4380fb25488aa78223989893d7786b8ec947d82ce0cc905bc
+dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz=c97caf7877097d78fe2191e715e3a45d827d28c27b4dabf0747f8ca522ee43f5
+dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz=b7794ecabc42698cb77c1c90d66676a8b1b3632108ab95954ee496ee7d6e5708
+dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28068a6e050abe21933920dba3ead2261f7d0c09687d5a86a5db51cca6e72ea9
+dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz=3860d7ec8564019c79551727a3a54c66453a7d654fbb89b8feeae75d9021fa77
+dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.gz=6c2a918f8d40ba01e648565c98ea120d32562dd93820e8f2e33abb2aef08e1da
+dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.xz=5d1edcc6c4be49849c3c2d1c3c173d4a127db3cfb615093e5ee396e0d0c77366
+dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.gz=a64c30d82dca58d09bfa38e72bbe1457b48b101157193a3ee33dd85922bbfe9d
+dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.xz=87d14b146386fe1f9e24fedc25e1bf9682913bbd7537047b0baef0d74cad5473
+dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=3f186913535ac59446e249f4d3e35e3d93a3f8207b31ee31b3f70af8344856bc
+dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=0c17a60ebac74a9cdfc2ec69fd71a21e370ff178f4c83be6020642b55b6d78ab
+dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz=327973698dd0ffe9b2d56b3b5929f82ec552f2002b4113fc9a738e27b0005ac0
+dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz=d7e2f768922ae36a9eb302667398ee308c13f829c03235682529fce90253813d
+dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.gz=13f327974170a0423ea6e7241cd3a454ab8c39b657a707c08f2e306a7a657b45
+dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.xz=5c75388802c0ddcfa51336883f4039b6f7963e0efbe47c209bb455c12951990b
+dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.gz=84c4c02fdecc669c5d26c49120fdece5899133c098f5ef791ea19aba33936dea
+dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.xz=7ea047840073e6ad3123a61ca799bc56c951edbb71cb8495ecbc2029759a0190
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.gz=dfb8207b4b3bc13a9704fd1d212d92a22a0e7a57293f24f28bcaa846ad4c08b6
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.xz=96940a84d95b4cfdde84a501758c9dd83f5d6cb5afce9142917d5cb3dd75c040
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=4ed66daf59e9a8b61d66caef4b2248be72049282518d7526be771301bee2b905
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=013d59e32097917b269c45a837bff380a41c4f6401b0c145264cca5a1bbd91c3
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz=270a0322dd3c2342745faa8797f4f64da8c0028b322385d209ff65cf04965a47
+dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz=9d54f7f51c99f17ba9cfe7cbe005ddbfe598f8af6df1dfccc9ef37029cc08b41
+dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.gz=9ae4c1d6044b2c3586791f127108e308e0a381e8e14ecc20b3830ae5258a03c2
+dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.xz=689225ea098a88a88e8e2269ef53f964405a6c31b3ee2bda0fef98da4ed9178e
+dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=f1d9c996cbe468ca93b15c76b84c544930d7452f1eff2968a298c885203f14cb
+dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f3f8c088d74c81b2457ddff57008cb908cc86e16d0fac60d10969e45210d88d6
+dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=fb4e5d66911a47bd63429686885cd5c7f0a6310b25622f36bb43a754300526be
+dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ab6c7d346bfd72f06fbbc198743bda35fcb7fd1e131c05c54935b6ceff282f17
+dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=32b2e0d5161f7d8354d846c91e5cb25530e78351dfcff4ebf0a6fba669e2c483
+dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=656fc4a8af570b28b3f83cd59d4e5226f15d11b5d8c26b58ca2c1b2a4e18c4df
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=13c98efcde78c1e187f728509f2950a0a407ba32e730877cb9ca4cbb4ba01469
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=6372891715046375fd0a04e80c95bf79080db2d136e187b02ea96647e9281407
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=db156e0d5db6f04621e625e92323a04091c049a8b5e2b4f7e0fb2e50b81ab2ec
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=b610214bb59b8f58be96b84b0f13e5f50473e21039f6e827fa16c446d0e9ccba
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=99f96b0bda31bf21853c96b3618408587f275f46ea9bd7d1fc741e58343a5625
+dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=dfa1f209f546b457aa6ef742a645f00f55c70fde86522c737f7a560494170157
+dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.gz=4735b29991a2337a7e2016c5a827635e17ac149372efafc0442a86b0dc0759fb
+dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.xz=fead0635c572aa4f5e5564e497f1b7e892217ebe52fea54aedacbefb32f6343d
+dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=bbb9b6fedb874a61d99d22b4cdb2d20d8b9e6c69924922312692aa526851b960
+dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=9e0d48236676dc9947565daf0c2605316c5b4abc06bdb1c343559c46b9c4e304
+dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.gz=e230ffa3d46dbe5330416cdf8b7235b8dc2cf119ef8990b422eeebd017ebd17f
+dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.xz=38a5560575740f92cb8664d204924cf7a2972e0f2f396852d8a22befd2cdd848
+dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.gz=0b0a9f95d10484207c52fcd8ab1bd56903b53f18ce46fe263d5b7bb085044246
+dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.xz=91f7655ab2bce397a0821edc0f523dbf2bac0af39a50ead106eb1de637ec5c44
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=e8210f03bc18661954f147dedd0b4af721d005866c0c4fea1e91594cd6c9bc2b
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=56a623817e6a600e802727d59d4cd653e84cb628695e39ecb23ae99065113115
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=310a408bde58335d8011af480d4f8c38745865772d71631596cef1a79f9f4fc2
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=fd6766ea9e828adc2e43ff1654a459785eed05ad00c7f6804c742ff8ae8f6b8a
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e663e30526d85d89f41456a3d5bcd411397cb69e7cb9508aa1472b015963fd18
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0361504ada464a7d21e7ac66fdf9e1e820695f3a8ca4854695e78a748c5c7a18
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=c375be97e626900d809390c61bf6f2d689c9fca8e58c85e4e02b694bed4c5ce0
+dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=c33e3b4f9098860f75fcc9a8f86c7e7173692ad4c19cbb2c0de068961f87c192
+dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=3f50d9afd9df4db85958e4575429dd4c80b6702a8d91c3f1d9327345aaadefe0
+dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=0016d3a6ec8351ee9fac2eeae358a0854a3c2b360822bb3ba670255e8f27f57e
+dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.gz=f23117b972ccd21c0a6f4db4b544401045c9f157595a297fb56d7e864cf190fe
+dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.xz=ab9be4bb25b1575af276cbec7fb1a1f8c683741b0f137bca7b4b61ab13575645
+dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.gz=673561456e26bc992cb6a888c34c0b6b13e1bd0d3e0764360a785a6c3369f0d0
+dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.xz=29c6f01c636bcd901b88e92c60874c454369efd41f690d74b1fa2adf3450166a
+dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=c214d4439676a19c057324dc736d63aa0328ac74c0eb9ced8d782d8bc89757ae
+dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=4baf85ac632750c35d007bcae8f23720208c5197f4a1d49b0a85b2b0e137f603
+dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=a7e81c0e80f2508c81ba9d8e658dabeb19af2de6f7365f6e377d39e99d8449e7
+dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3f37f746aaa03107573a3a2b201c15bf86777ec405dc03640e7d3f24f718f67f
+dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.gz=fe7c7ecb8a8e612caf0e7ecf04d18ccaed31d8b93911ded6b3cba0c78fcbbddc
+dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.xz=d571b714821de4b7d2accad221b5e043e7f9aead8dbc06586f4f7ff3f3f3e38e
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=663396f0e4c45bfc041b1a502b64627620f499ca6343664633761c3fb1c2229e
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4d8c47d74958e3b1058ab721e9c6635774afad0252f251b0c9fe4f0895d0c81e
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=3cba82809bc1204b6e8f62877c5e9f9a08f111da7d439032cc30d55be0e88fd7
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=d525a4dde496e72fd18c6f2a525756d652ced436007f513267e9201d8b1c0a40
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=ec0311a0722f205b117160817b2137e9a73f0f4e540930d61c831ceba1265f0d
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=c63c4a28225dfca26baab129f06d8537fae5710083046f203a2fb73c50b48671
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=52eae1bdf37366bf406cff95e5e7979d0651979ae5ad4c036e8badddc8ec8b82
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=542791fb5cd80fe5515ab0812c9fd8671f083151d4262fc76d26f7723ba961e1
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=91697f75c762bdb51f19348953768a45bc37c389c2e904a56f4f092604ed2d1c
+dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=a79a7a5974b365f70598c413da3db8262d14414e3b4d48dde45f529bca4c6ef8
+dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.gz=6eec497ec2aaf6c5beb8e6dfbeaf32190b6f7206aebffb7499b5fdd7e5e7643a
+dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.xz=234924a6746fed2efa112b0b805d0ca56252b6cde82e6422774871e9c009fed6
+dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.gz=1b0cd107412fae22266267bd8eccd2b39a36afa8936da3888d0bd0d2f4cfdb1c
+dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.xz=0d0d1ee48f9032df88ea7b3f73f06300686f4d5b9fc16f1d4554caf8356cfd74
+dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.gz=72f0549de44925bd08286e092261164dac47826124123e3fe707411a3dfa756c
+dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.xz=eb45acd55dd70be3670de83c8cbef5b6ef05827b3f97b7c71679a19c88f8f3e6
+dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.gz=edd8dadbba618f2a786dfcc68e4a5c7f2b7cf1528d1c16ca6ddbc52622df95c6
+dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.xz=ae59c5d77b31aeac30c22104abc0abda6b7f725419e9f86db6cae634ededf262
+dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz=8996c94269e4c60270d253ea75bddb9482facc441ee2314a387888924bea1d92
+dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz=f6b59e3d6e7f0e458c048ad4aad9a2da23f3b54aeac20a905d2e00379da1bd6a
+dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.gz=85f22b148be72691214dee620eac582405dc3b8937d2ef7c480c9070b963af3a
+dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.xz=4b48538541dd20fad8569cb3f0994d5ce6aceaacdd8b319d00b0234cefc5c267
+dist/2024-11-27/rust-std-beta-i686-linux-android.tar.gz=6e5ce19fc4cd8cf4dbaca8b31f4032b08ee413ce20f354186e4945efd4e8b6af
+dist/2024-11-27/rust-std-beta-i686-linux-android.tar.xz=5e78b98abdf2b7348381863052c109beec025a5f68285ce72e6f6e9245c22ce3
+dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.gz=50057f990d1127e7d693b1c5b9539b19262a478130bed51dbc2837d61d2db6da
+dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.xz=ea524b276e42a1cb918625df12b8d3397ada5ecd43bb9ad5c676747e1f916c8b
+dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=c7c9093e277187590b86ea02fcd940071c8bce93a894396d73953276ec58eb1d
+dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a67879ff0dcc591d30a155fd972149953eaac3b139bec9aca3a383dc277ddbc6
+dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.gz=a086c8272f9c7c0db3d5de37b027478dfc22fc577c613254a821700c645df3c9
+dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.xz=8ac4b938e0b643e47d6d0ba6e5283887fcc73cb1a825fc065c35879b085d9c28
+dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.gz=3614b95b54ca24c598e3ed6e14aaa86f7048c2a5be2b3e9f97d9ca00f3d890ce
+dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.xz=6d36127f5c113b01300fa0d54062bc1137b51d2514346c8d84bafb9f2c56a972
+dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz=a6d33a96eeb667f3f4649ea6ccdd6212a183bce85f095ff7db5036c3a50d35a6
+dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz=bab1dada484d61bb96e2834da5fc6ed5d4d788e6636849e9802f9fb6bff45d55
+dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.gz=0ac331a1c9e384430a5f316809bffdf01bae3ae9cc1f807f07142ffde7388602
+dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.xz=136341bbf4c820dfc98e96cee41fa0e9fcbc7d81d2772407efaf1d4be6d10f7f
+dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.gz=32f06ca3b2752a8687e2f282a59823671fcec672bffc0775a9fb27da50b6bb11
+dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.xz=b2f376089b39a34f3308833ce9bf65200f9665e5c55bbda3e5b7e9c5096b7e67
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=a2ca950893c93be71c7db707230b98674a29c013546e27d95bdf8c3c6eebf9a7
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c70b58f4583578347e9f0fa20d17bd5fc51d88717095e05d73091209f2a363be
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ed284c40b6253c022e39718dc2af2e4100ca7e805d35d86aca04937586f26ece
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=3efcabf46e0d02505ebf0926c6c14e0c70838f9b510f2328ccd98dd0fa977794
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.gz=9b9f8418fdf64fef652f15b28a1a1f2f8c63c18da8b323994f10f921010721ab
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.xz=fdc673e4b250424c6dafc18a165ffb592aecd7b897e483af8ca54aa145a0e6a9
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=802d22c1c364a58402f9313c6ba2f58b79f3cf3163842a608b78680fa2b3d476
+dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=dc4932d91d8a2887d309dbd6317d6c41afd083043f44742138ca7c97f60b931c
+dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=636b19ca036fc7ddcf358062c98f6bcf31e8c2cd035cbb9dc0a6b96c81217f7c
+dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=31f80fc50be95bf665d21fe52b714532ff34ebfcdc0c975bb68f7d2f2cebd0e0
+dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=f2c83275df652bc5b387525e77a1aa30bac31fb301b304ddd7e6bf402e140c34
+dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=41358bdb20fe3a97a95fd7b656b1ed03d5b8012354d8cfad2437bc9ef6c7aeb6
+dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=49b8f286b4abb3b34bd38c92ea3e15efbd1f623d5efa7bcff10711b595363579
+dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=283f065701c77fa47a2d5413d20fa40989fbbcc75bc938889de6c4f9b6b9e53e
+dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=d0ee5ba5dd6f94dc6ca981be0d55f2e3f51c2af25877131a7a74e0ab9848dc3d
+dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=79c78bb31022ec8e7a3fad9823c5d22ac553d389104844110473d1877d8c8302
+dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b953686e3034f2b51033a2630328c8eb5f59fdf8ef4e26189bddb8efb4c482cf
+dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=fb25ac2e68594d379f915f0555b3ded2b1a7b5a67144e12eb62949f540b0d957
+dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=fbf5a16a57de3a7e846389aebe18bc7871f43e67eff39fc9b4744b5a445b2639
+dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=55a92aa5770924a21b706724c15f58d66ef2ca5b630f7025f6ba1416152ef350
+dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=b880b7209ea604761ad2a46832925d32fc547737b879645fd3cf99ec235e7b39
+dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=c48cc6a6fda06fab014c0b8fef49006dd32fb71f8e981ba44a0c25d47fbfe034
+dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=7d133b6c8d0e8b8ec8b65a74ed8d64a22e2fa5e4f6d4a1e36f9e0ebb8826f40e
+dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=1c507e003c38115bfffe8701df1ff7aed6ad16ef5ac4b383f84bd2d6aa0216bd
+dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=111a909b3d1a04b328ca1c1f247ee4eaaa84349eeaa8df77f7901bbc0efc94c1
+dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d29f92ed071c60259feaa8005eb5392da549f8e2069fecb1b77e112f89cf1bbc
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=241b1ec9ef6a89277944c9d8021f521284dc28822c5f80513b6cd94d2bdd1d64
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=9f5b02be846fa2084becc5616f024094d47beca102442ac7a0e3588e0f12ee7e
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=7272eae1625415c0f57bf541dd62c14e02b9946ca1de04615827a1f5218c2181
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=d4bcd0068d3c9e7351565fec57ca68d36c9ddbfe59249a6bd2c56930ebad2257
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=758ccc47004398add2e3cfef52e4839e14dc4d132a215658e576e590401a28ca
+dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=6902fee1027b0136f8dc5179e69e24ed9e34366e9409129b9ba223043ddadea1
+dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3024570f3e382a57fce0e832c52d080a83d42206d8412b724361bd1f0087ec4d
+dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=20eaa72b6fa32b9884b43030a0bee554bafa9de3f3b51c5768ba0ff47ec492c1
+dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=a3eae70be3fa5b0a56cc88cc6433cdb7c42b3b974caf0d879d21a5219f4f826e
+dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1da88d1882d4dd1f15ca97e016f392a01b56951882ae75929023e83fa557d796
+dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=387cc8ccaeed6f9c6a8c9d21004e45ac97a9739643a63448eb893e13ed4df22d
+dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=1b9afe3631fb7847b2a8a8f483fc00ca203ccc18ae298339801dab1c7b06b3b3
+dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.gz=f9a4d2115d6fce06e0da7a9f579b197d383034c218573e145b3c7dae0aad21d4
+dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.xz=c352bc631e538d4e68eaaccdfb9dca1c9dc8ff0ef4a75d8ee91016aada39d717
+dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.gz=d97851ca9193d98192a55aeaf695973ac706e6ba3e198643c200cf410817b424
+dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.xz=89a6524a3743e5a769a583b4a6bf8a76ef5b45c67b7e39da7ae24b687bed4943
+dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.gz=6fe614db166618a8f2ccb5807e02884daa8bd8dfded2164f88d79fc688047020
+dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.xz=91c5e4f4575ab004119797988679077e5057881ad9a7f6790b673dd062a8b7ee
+dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d0e05467fb1562ed7d6687a50b7fafa14ba0c2aad328f0e7c19eaca1ee366475
+dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz=0473372df5fece49e58efcd3b2a702bb93e47ec149b38fd5244ad667804e7c63
+dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.gz=e6b6130a1a571325cc1bda8ddba6b2672104c2feeed5c93c6022bfcc8ba4b247
+dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.xz=d4c739c42104e04aba55b96a3ad434e11b013ba44649dd3a648cfbb15de83eb9
+dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=e427d5d6a53abfb53b436df96457d58eedc648198fce6b1d976b50de18cbc31a
+dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=11142018c11849c21adaa7096abf50d0c923f3b8f07d67eb96d6860d428e9b27
+dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=46596d8f2271dd5a6f0f84387ac19d0e81976adfc6050b6aab6cc554102fe469
+dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=f3d0c9db1c50a018540278433fed2e0ae4bc798aa0dac87cf0f55ad1808618a1
+dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c46fc4bf174fc54f5565fa04e80efff4e853642e3e5f0bf5b696a2bd6e7ae817
+dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=706c10ef22cc16b3d4cab8fc09d8783384313b9f774229470b8ae1dd292850b2
+dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=b9cec80ed374f7b5f22f1446e3f2e0dacfaa0e2d4d6c631ad66cc42a23e156f7
+dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=41c67ee95e72a3d10bdf739c4841bd937c4e0b19c33451724c1f603b4bd2a318
+dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=5ad8603f98cff0d5d015c72f3a55730d75d59680a867c067928bf4586c00d805
+dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=61a75701f7e000f86f318a04dc6746f029fb933e0ea94944d76c7eefca1f24b2
+dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz=89bfbfea23974ed75a53ff134386992e9c257d3e51a55eb49847aec9c5ba6b13
+dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz=e34d1586bc6767b4b244f98754badda706645fdec7168ddc0a409b9f95f2b18d
+dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.gz=8a88bb923e138d0015c8f46bc1c3d5f2f5f75f40dddfca72a49eed42c080d1db
+dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.xz=79a980f2b999c3e3b04d7e327bd2b548007039b45da705847c6da2bfec3ffc04
+dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.gz=454e2c4b46b4684e591c6e4c0f1ce8e3c44623a29d561be3a481ae008072dbd5
+dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.xz=4dcf652ab51fe03c4691de46365218dc483cf1f7c2f5a552a38509685a0ca873
+dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.gz=c2c34d9b3998633cfa145dc2a5568a99d1fe26b91c5be55a08870a1d27db4af7
+dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.xz=4d5b25e4b5fb71d879f15f320f7513eec1ad078d3ca6f525ebf56b9620bdb5ad
+dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.gz=e1385a340d3d9a4003cc456156bfbb1435a5255b2bdae3a40b6d7339768bdc81
+dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.xz=245e7914174d213ddbb550b09fff200f419bcd632de98548a470013891666410
+dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.gz=d5d924ea001f914bf87df8765b013db6e838a930a4865e95f8d35bfaa86bc81e
+dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.xz=bb98d0d55f38f2308bf99d4e5f11842683452571075eefa5b4e1f18f2bd553bf
+dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.gz=edd5e7ea230a13be750dd74c5f7a7dee20db8683f7978aeb352307a0ce110b9d
+dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.xz=c6cec9a501d9873e3c7abdefd5b9418f7250c8cb915be8b816cb48dedf1f201e
+dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.gz=e970c2a4ebfb69219dc66e4c7541cf22c52da5f94983c7c914df1f93beda3d31
+dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.xz=594ae9bf5f1501322d986dc91249a48a61c22371513b872fd63e134097ac55ca
+dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=d57bf579b4629417dbe1c02506db4a4ba4428871a2684141d21303e6c99551f5
+dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=714db83e7563a5f286fb37bc629b64834a9ed981bb9a05931122072f95e39bf8
+dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=feafcba9c46ba3e5fa0bd9b5bedc05ef3423c9962dc4d25a7b2367e3e1caa679
+dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=78fbc8f45df64dca21da7223b5d081111922f2268fcc4f1f83595d159d310bce
+dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.gz=74fb57da7f2907afbaa2a7a73847273ef81e2d6902a326f1ae87767677a864d3
+dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.xz=3216eb73d9c9effcd2a2de7f63d78055c3d7e50fb8141e2910a45a36ce744ffb
+dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.gz=3df431c8941ac28906c3a6568d3debe478d9349d868ea8bd3ad79e65792c20e8
+dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.xz=548c2a6104148bf0da21bf5e009b80522fd15539077a62021a64f16282815a5e
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=235228431d67feb4c8e6aad44e20bf68574f335e8f948808b597ae98d827171d
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=5a2d4ed70aed26f902cf45e1dcabc5f25884cf6e9aaff775405ba9c1f0a5cacd
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=818131158e8be6af4b762750f7927c4a799346c94059a6073230da79b4408720
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fc08b39833e2c9319dcb55cef5c6d1f0110aea794c9a6f163ca39749a22a94b9
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6164c3ade38c03113193301b815c52df0ee84a4ca1c8ef21e1a56d386e28df00
+dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=0846126e6c4cf2b5184979b6025fbb7bddb5c22905bc7ba31fff69f6b1459280
+dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz=ae308e29be13a176b26c142347a81facf8c11ef1a28e67d5898f4f2a0d3344ca
+dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz=e80bcba8b011a4dd3f7b2a2cea69b5a95ae2cde9b2d9078ac8fdd492ac162139
+dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b25f0d605b7f4a2a93adb746e32f59bfc26af569a4169e9fb203cb33751d1575
+dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=010f35236062a651b1b54d7c928068efca8dc486856b84b04e98f4f97583bf32
+dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.gz=db3d258c2caea73b469feb9c11fbd3bcc29d22c3969c406321d11f05c24974ed
+dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.xz=a952b0c2bbed9085525c041c957f00b6b1020e031149dba70c09a1a0d40db3ad
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=817d3d3a931eba2255bd5721435cba7604fe37a72c18a179c1fd5f06dc3b97a1
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=170a54aa50f161576d4b0d103f2ab6dcbbb81ee57a5a47f7fbd181128f6c17ff
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=ea991dce55415ed7462abbeb1ac1c70795cb628b0460e14230e8cecd41117fca
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=a8f620c3a641f8f4c29d88e4cc54d7637aeb18cf8eaed8571ce558835f742601
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=875e2e3309b1deccc1a4476e4847a2849df32e0e2a394e4ddf3b4abd1feca534
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=23f21ac664b3341771109ac69d094518a512391b86219ffec50725dc68a08504
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=680f5b2c63f58643bd34f9921e2c1699a549410ab06bfd04ce991907e8fd7d8f
+dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd10f6f3ce39489b6e3f3f638573e850c36518e3b2e8ffad0c50c3143e3a8124
+dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz=fd31ba490f0bfc53530e34e6e5ab35a52eebee616efc8ed18d473065ea885230
+dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz=daffc01050f5cf0b5ece91717d7a4c42cd4a148c4c11f641b494d9c375df5177
+dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.gz=376d571641a9f1f75fadf951da91bb73ba94a5495d7d33389f5f914ccbec57bb
+dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.xz=ffd9e826537dc94c6d8e767ef5a61d1fcf0385b8ccbe508ff9177de0fe772939
+dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.gz=447e434b5e40f7882d7adb6d0346629e0e3e92d0f339c7781e5a437898a84b4a
+dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.xz=bc21caabcb492ca648e19a8f3b9dc1a1bf7792135a202831deb554ec3ea11077
+dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.gz=40ca7d9ebcf6610c26f2921c0560729e708f5661bf6167266e9d8cb3987ad0b3
+dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.xz=06966d5901f5d9accadb47c4d1e561f3f95bd050f3f8e78f30000389f39e9b6c
+dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.gz=e1a24f081ddd93b483c0f1c196bae676163db50fef0a994bc47c2a7c98c9dfa7
+dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.xz=d51a5f0669906eceeee4e09b079828e2ebf3404aaedf1fb20745339205270ee0
+dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz=e135a5f0f83432b58d9e093c6d560b021a133707e39e1ded90a28a9967105e0f
+dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz=1fbe65015cb8c7ab0b863ffc6f7aa72d3bf52f7830957ede8915c61a22e5b993
+dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=9d4e830e9ba582302865fcefe31883cef4a471e77d46e70838e549ca11a0fbce
+dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=233f6347a36e806dcf27ecad4906c90bb3353051f440a819989efcf091cb78b8
+dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz=6cd719a7255a0eb1f11592b9a92d0aa4986363f624ee0d6077fcc253acab66a8
+dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz=b874ca8285ad1936adc70a9323cf80f06322b1e6d5925f54b58500129830f0ca
+dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=ec7200319224ccabe814cb051e51d147f1ae8c763413002fd03c9263a02c2320
+dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=86e96c80a91862e59123272c80f1cfabdca56bfddcd66af4a5e840af7421c4e1
+dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=3f7cfdcb28fe8c3f0dde58c24a0c424652b40d00a24fc50891351fa5bff5c15e
+dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2d5a184b0103ac943ec4f6756fbc7126773e739e0d120acea7b3244c7cd19b1b
+dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=9a77540943f28584d90b4bcae4e234cc9d833eb732f65d7fbd680a0f4e915da4
+dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=7696a065951b7d7179b30ff2fd16a05675b6bd4250f293666b98ec05299113a5
+dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.gz=eaff75076ad71a4291af5465dedf0fb0998dc171e35ab8f707ac63b43e89c38a
+dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.xz=205d3d19726a1a87a1533d94f77b73ed9de8181906acb48088dca22835aa7a83
+dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.gz=58da319889533ff7be5c9142c2abdd1ade79de10eb83d7ef82ebd93b75607f8b
+dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.xz=5ae699d0f6b9e210a988af5b8f2f0c4d62fb1695ed6fa55718fdf05298039b9c
+dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.gz=362f6338ea929ceb632307031e049dee1b3ed998f5cf160654c327c5e0e7ed39
+dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.xz=88f14ca7b5c8af006f3c54749b61747485f7e93fde4c65b5969e73503d12c5c2
+dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=9ee8f29e3e715cd7c85e679fd01ca724a27503a50edb0e6f8912f289630bc7a5
+dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=4c643f0d18ba101c2b248e1df32ec3ddba82efc0d5f9b47945d484fd3d462794
+dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=f70952c63e2eebd05acc326cfa667595535fc36db34bc0262fda4ba100ff2145
+dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=0546a908cc12884801c35b461f98db01e87a7f92d276ca6cb6b89eb76c596e2c
+dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=3534e839b34603e4e2b32fb8ecc76163ea3b9cd9907c1a22fde4165860d1fb56
+dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=b402a2e73debd81dc5cbc866f00c2ca82f676e2f923193674969af0ab34ad311
+dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=fa69011557fdde5af1f78f33f9ba75a1d6f4488b9d8edd2958582593dba347fe
+dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=679be0bf62c7371b92f1824c8718662672ac3ef2d79e8af5c752fe34effbe333
+dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=ecc2ba0da5c1057136eb105ec0727e55396e414d75efe0c2b96bef0477961574
+dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=a89ad44842df861c69c6633ba79bf4ecefc38419d5669b6f22a265dd7be836f2
+dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=051437ff7d177bdeb7a5a0eb947d27b8cf352c8e809b9311a1cc21b785a5a8b5
+dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=1a4f50972104a95c404e778279a4acd42176cae45f58d316d601e7f38dc7bbc0
+dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz=bbe9812fe890b900e71aa4714dabd2f3e67bdc610fe0bbd5aea645ee807dd0ff
+dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eebac7e8555f44ea9094750b61bd11d758197a72d4d436e1713e4bca42fa8080
+dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.gz=6773b94f012a3d3589e2bca28f35dd23208fb245f107e4a17b8b3e7f893c038a
+dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.xz=d3a20dbd60545b0162dc06499317e342bea077cff369e053eb89e85e2b640188
+dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz=39e16c97c0b22533dfa674d6e8f5bf5df256e2b426d02dca5ed33e246f18d05b
+dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz=ffd939f901c64a17c3f24fc69744cd2af1c176a45d8e5fa8209067ada403db7d
+dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8addc12e74a983f3166b89d1d53ce87c92f38c7c3a62ec7c66580aa424d20516
+dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz=8e5622917395ff50e53b237e7322f1faf2b64f0446c41ccaa0096e57a3e7de69
+dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.gz=2734d099aa1ada79346213aec8cc7ebe40312df1dfb40a32d09ccd3b6622e025
+dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.xz=642edcaf16dd74c0935d28ce9b37cf1c5ecb9c03bec30f6ff0e7476760ae7ca2
+dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.gz=4f28de38005de48db7126dcb698b748063341de41dc71175605301837a3f7336
+dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.xz=ce18692f99780ec09d01816277ee4e71785bdfbd7abb4375ba8d87c1b6905ffa
+dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f1d692c3a1c280f34de167ef26af3c13a6d0a3b5ae4fb86b0a9f2178c3287a94
+dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=21f477af2b49ec8809bf8bc7b4c4919c7d2ac57782b829f5a0d9ef1967c5d71a
+dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4bed61be221c1347b1649f54222b27e2a3577b84816ce1099c9f0f461c6e9e5a
+dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz=33f463209d50ca6b04a8953c87d2177a84d1729d635de9a7c9b1a711ccb5d751
+dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.gz=ce46b5b2d767cc0d790d8fd21052ecfb787dffb4218a238a339fe5f1afd26d6f
+dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.xz=0afd0489cb4231edc5bc1ef24a43c3f1918f681f08c1207d184fefdb46416509
+dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.gz=6e5f1a85dad2b899567369aceac0102943ab807dad7e218c273b7b4d6393dba7
+dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.xz=f784ac4a6ab180675396adf8256ac2bf2d1e823bef106d1c6c59911a8360692c
+dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.gz=22f1e9299a24aebaf9a32471ddc6cdbf856b455d059ca077170aecf5989f8772
+dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.xz=7f3fd047ed5aa85ea6ca2b0d6103f7530d7d070c93b0f212c9d1a6491f160cbc
+dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=f383ecb5cd654268f00be1f577572993c38e7386a1e1d18b864338e87c7b2b42
+dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=b2043facf587f98a8f10a92ae129b7f608297709f4ac61d683b7c813cc65e41e
+dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.gz=6678d45195bd2a7b27ed2d4bad3790e6b63e376da71d112b9333760ea375c40f
+dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.xz=f6c77e80c9ea4e312fc2715a9f66ea9a2e6344e3f04ab96cc572e4c0e8c915db
+dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=be8c0dfde3f09bf476d6600b530aa498b01415015665429bebed8814c7568b73
+dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=4315f7623dcf0a278cccb6c8b397a29f83f70ecb9b03588f61e383e5ebaa697d
+dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=c31ff694c68f28e0f462133e783a5d732cf9c539737fc8dbbfd01a53e9a456c3
+dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=2553ae5596b8273d8a61ec66d2e20d0c9733c9f791ca5c56217c60884f0ccf9a
+dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=1842cf2c26ab474df47e74720c56997e270b37609f840ac50ab0b05064cb38fb
+dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=e882b1cc2814e3c97c33991fa0a80de62556ce8f4f88307f6338a90be32b045b
+dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.gz=7c6e08b841f21e3b8953e51a6a9fd9df0c719e8defd7b1ab0660d8920fe72185
+dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.xz=137aec194877446fec994a233427db419bb4f2910151c456c3ec80d9329628e7
+dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.gz=52ba38277ac3f80d124fdc8dd1709b8c1115cecfc53fae4731da8615a63f78cb
+dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.xz=548d3eb599334ab98791b8ba27decff8b0de98dfcffadc994ad38aad6255cff5
+dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.gz=448071394d5e647e8da8f64cfbf85e8305d85ff9357dd24737523c95eb339ab3
+dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.xz=e25daa6264cf5e0a7cbcfd827e27a8e276c29c88c86cc15977c1a1650d0303f9
+dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=9f080cc937e7209ad83fdb8bf4b2cd7b080af83dbd9061229f154785e273bfec
+dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7d537f66195c581ff51ce8f53c4687a762daf225c7f0ce76393953ab04b804e1
+dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=2bd38261a9ef33ad687b3edcd33f283c32a493a80b56dbefc822c1116edb1f2f
+dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=7e63dff1d8abe517aefeb4b1976932d23a9a7ed5e4db2398d8ba2659301f639c
+dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1495b2a49cfce014da72beb691e6c477d189ef34080acb1761b588d11b75d27a
+dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=75da94f1ade2ef48674b77ded595c69ee715f62f9d9dd96e72039e27807b7314
+dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=2d6b826fb4d3d9b61ecd3aaffdd1334f766dd5a5fb0d8279e0de26d381c5cbdc
+dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=f5ceaca2651d6002f232f71809458ad912bb5f00030790e907ff7b0e12c9e0c1
+dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=1a62f307197c6fd08fbeabef89f58842cfd59c6d62f530850592fe55852d61f7
+dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=4c65fd6a5d74527391fbc7c242a2313e5290209f5a15763d74eeaa6cba0a0ed0
+dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=8ab9f735a98de1949e65d51c3050b29ceba3ddc28167ba0180353253dc726392
+dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=0367eb23a9349ebd829d59fe0a2638557c8e57205e48f66a701b238461385bf2
+dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ffe9100ec6b81b081d5f9d840bdf01c658790d7e6bc0674e5ebb6b28f79c2f7f
+dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b19b1b28bb7ddf8cf977f102acb623f65d5117c44ab8b62cf197f2d3d33c15de
+dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.gz=d986de5c01bde3469693dea7cb4248155ee9791550aa179d601066d27e45afb1
+dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.xz=8000e46ccc2598fdb770c69c68aeb18d94db9b2847d0509f7a9c51ef28714ba7
+dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.gz=c701581f28d885889ae5c845a7b34beebb04a4631c2740e9333b69390cfaf499
+dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.xz=fc285792e6f626e133edede613a9a9a90ee12191765e2f0beac642a3b3c9ca12
+dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.gz=91afdb71bdd54e5c04fc7c933dac06d5e769627e886e20eb712524e852a01966
+dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.xz=2ef7018c7319e3a299c5eddf36748d9d293ae43eaf54662d9855fd211eb4658c
+dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.gz=02234d4c47478112e01d51bc7dd48cd467293e1eeba55bd383d08bc7376c471d
+dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.xz=a3e6a0c7f31278866d97816c5ed434b1987e0bc5a89b24283e836402803c1388
+dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.gz=b238ab536ac963929884da4dc9bab43679e6fa9aba4251c73ab7e5cbe5d8eeb9
+dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.xz=797ea7a7643a8302e45347f21c4dc6bdee617c2a9d9ccef74ed525c7d2e9dd91
+dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=d630a6b25a08af85d3d426e73d3231e018e0ab7176a5934572786147fbbf3823
+dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d0259a0112f452ee49b8c9bebd760ab8945e5bc3a0d57b1cdc2b8e24accd35c7
+dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.gz=5febe478e5040f0f74a14c23e78eed21b080900d875d6b447354945c07677a6f
+dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.xz=552c35bbe76a83439e66cf9ccd522d97e43a8fe4f6aadbabd1f02c4b2c1814dd
+dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.gz=ff6db2d7b84e1b01c81e494de15ccd07f60fef6dc60fa46d47e128ebaba4022c
+dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.xz=b27f89b175bee3769dab1c2d0c54f17ff3efba2038f3b600f4077435c7fd21d3
+dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5b5015483d0a98e9dc715c3cc8c23598c02fc14ea6e5878790ae68f2f1c8ef46
+dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ce5706f0397a1b2fd9e17dbf34ccfbc3e8c87cc81c92b54b81fd33accc2b7c06
+dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=3f5077c8743b5c4f233da7d0aa0aa13fc488ef0fa9da24b002bfa413d52dc845
+dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=087eb30f24ba7d8ee42e28bce2a6cd75e5fb7ef5dca8a738ef23fac82ad59566
+dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=28a716ef9c5318543559ab4c0c2d062b0deeab1ecec80d5d83ad5effb574f209
+dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=99cf9ec4b7bea4281f64a613784350a8ac34e9b0387fed7eb26d6f8c21c83735
+dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a23c3de89603bd4d1035a267e6ee456c6de12efa4029d76ded3edf7c69285a15
+dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=462dfd28b631b5a6d8277920cfa8037d8583cbf6a2e5c9159c492161013e820a
+dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=44af5b13726cab40865580df8bc05182a2359eae64e41a92f84790ef55ca6bdb
+dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=0a7c0b207e745d01194d96f0fbe2402273d630d4f1aa05001a5f5371c9585a2c
+dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=66e2fc688b8f746d15c0dce042f2a94e06c5b652d5e0b6534d9e992eec186784
+dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=15a2e087f7b482fa8c027fe6e6fbaf846d784c8e917fed375048a297d5e13c45
+dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=71788ea2544f8349ec548a2f150dca2afe80a49deb91c00c46484a5e3039742d
+dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d9fa7b780b9d8b93549abf0a3f0e6f31cc8e1e991ddf682adf3b616fe2a1f0c8
+dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=30924bad51ffa62f762d4c000f86ea3457b590f6397d65755c711ff7f77ac129
+dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=14fff13942e6a65927776c49013249b2e75aa3a630667ecf49c9ba721e47bcb4
+dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=02d82688bdf3bd3c261a4a6d4acfb07835e29ce262cdc3165ba849a6a8490bcc
+dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2a19b55bb609542ec49dea87e3b67532e5d18df8be43d0ad775bb34f4f9f96a0
+dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d07ca0ddfb0dd89a9cc935b2b9662379bcc9503cb28a28d68c5165f787a7d762
+dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=de8106801b1e49dfd8a4fffbfc2a4f949218eaa011ca2085953ebf2a5ea9b141
+dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=309024f86e80a4568721b5bb61aa936e027accc251fa97acd5043b513b325576
+dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=55bf234aa2ec7fd4c6a7179f779d790e7f62969967519bacfeae84db5cd29abe
+dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=4bf9571182e7ef40e76c7e5905fab8ac35269ace390f5007480b4951f80cfa3b
+dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=2a2cde80fcbf68768ba7a99cb059a0cdc9313ad0c934383dde9598d6147ef756
+dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=b747fb16b15cff3f9368ce1a1f5cad0d2930bde5a609547a3afa2679d7ab8a1a
+dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=b861f8361ee806d83f38afbbbf312e0e5e4d8851e7048444c409de1a83484446
+dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=ebe56700ad0948e4dcd9930730f7df8e01a5eefca1d1157fe12160d782e2a5c0
+dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=5081c9b8677314464d8a3a50220809def18badb2269d2cd8b7106f3547b0e25a
+dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2ed9094b538b6450371311b742f2d309a1f40b2b4c84deb9867059336b76d1b0
+dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d9d52d9b9f4da7a457d05dd4645885d092f170bd2f751a49b4ab3b88395a5248
+dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=a2e51d381645c6bf18502ca72fe9f10ffd309281dae87ec16c5627f232f77e50
+dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c526efc054c33a08626b882eebadf887a9aaf8fd60a4adf6a146659a7c1ec8d7
+dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=04e5b7c97b57ff7d967abb4f98374f0833108c04f6edf482b8b3fefbde340956
+dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=1829afdebce1c3fe249f81958de68c765db18b431927e54fc42be37ea4ab8226
+dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz=d6cf138d02e50168f8ee4a89abb2a4a39e19458d060d7b46cf227bba1fd4c0d8
+dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e8185262c82c064c4bb9ae6f1d3072819410de9cfca943b77605012a546c254e
+dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=64d78f9f05a978b95b9e22a63bbb31dcf98152df5638f498a361a96d9d2b0c04
+dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c07041ab84364ace58a357c18b5c4dca037852e1159edabb02f4579ac6853b4a
+dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=7ef0122ccd3a0c77c917bd75e93358eb95d7e87d78a165c724e3f0cd90f8209c
+dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=d0d0566a0a50e1e9e7f4251cf207bde82d96c27016f0a0acc364754561ab4881
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=e4854528c31316894339bfa97b07ec607e8956877c285778e555885ce9c8a068
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d79c9b352ed7b2f132f06dcdf360527502b2153beb09cca968a5ced521edcd39
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=df76cbeae0a61506a29db22e8743d16fcd97ef2da216ea15bf4d6cd709814017
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=103cbb30bbe92da6666d84fab53dd7fe8105c2ebe62eeab5f6609488e62a481b
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=5f3c61663a319d6162240192f387e10ab87e2a972062198082158a243b667d7f
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=221b45c3928b1c45fedbeea987ad80750d3f55fbc564cf3ccf910a68447ad725
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=18eb24fd665ce1cc4ce66b37b19c22397bff9369963b127137780870c179228d
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=bcd09587a21ea10953a14521e9e0ba7b5100e8e15b6a10cc4e7bd359200d5279
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=db712c5e1d21231770e12dc95f6bcbe2f1d04b9cde61bc7adf8b529b41773adf
+dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=43303e426752dcd15964416822cdce0e5f3012366a9b77f3d68e6011c7bacd0f
+dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.gz=95d543a835b11cb5ccbf0578df1ce4e1846e4915622d23a36cc6e18e44e17f29
+dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.xz=db9e0c51c35c81c2ec8be0838f3231f7374917215792ffee159e3d7ffed855d8
+dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=bf9b83d6418bf97caf2df70a8e8298cd8fecb7b950cdaaa2cecbec243ed57c74
+dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=bb520da5b522fffb5a20eed4390990c2ab9d22eb4f77196535a84ae7a434c9f5
+dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=4072d9ca2d617d09d394139c0b8608bb8b2b8b2b4fa450f13c41975a16a791c7
+dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3d75a8a534e86bb55b63f5b5b2df66ae47862cb7f3ecd1591a829435031d7279
+dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=3cf05e90bc1f95e92cca4769f74055245234037009cf464df3062238c88bc2b6
+dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=245ebb7886cfba64d667630ca8bd672520cfece0ccec3b916e3de0f26aeada52
+dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=dadff4abd2f169f9aa1910d4ea247b7d1f767fca74238ad31485b73399ab6dda
+dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=ff97e1201e9a305673e8a9b740b7696cc4cb5e86bfaa3e137cd8e3e28cffd7a6
+dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0c411e0824140323f51600d387d52bd01f601f5539d6457815e950224a6d29a4
+dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=dc5731a70c393f69555433d522cde8a52893bfb88beec519c1bbb03b2a0e060c
+dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=01ef2f07f1222fbf3e0cfc5b957c287fb886fd0bd08cbf18f90dc37fb0b63541
+dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d45042b3ea0c0ce6befea7bfdd731e890dbd1f47d1992fe8718a1363f9f18779
+dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.gz=5437da4c0b73d203789829512d856a66c1697d95afb1ffeaa6347ad0f7c04672
+dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.xz=a7cb4cb627d75de1ade9211d8ea489ada9ac76ed38909751861ef0cb729dcbcd
+dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.gz=fd6ee6fc171459092e5e8a012d9cfb7491313e021d1c38965605836b5b101b0a
+dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.xz=314c7cd558a3654db85d75b3ed71da7cfec3614e4a5f2c449dbc6663b64c7e3d
+dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.gz=7a1118011b11befb7df2df57e4450c7611bb3503b3b3cfece9c9c7d4a304391d
+dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.xz=2cb95208e77546bcce56d8d5646c3fb5e49ed711894926cb50903ba10431a36e
+dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=4a76c4493e5ba19aaf14947a6c2e28ebfc7f2da530f1441a9fdfa328e15ea4cf
+dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=9b361904c691e17fbf44d80c7f7789511db1d8f251d65ba9cf6fda7f06fd495f
+dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=e89dc76ab061ae23081aee1619fcbf4a94e3acefef6b9b149231f3e1c22f9ec1
+dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=11266d557e6d1d9155e6f04f65e4815cfbfd9f8e1aaa47221030e3ff11b22f78
+dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=30f2eae1b8694607a04c836f750b4b7c204e1e14e52ec37885b9a821c2c9646e
+dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=495316e70b26140c66b074e9d7f714ab949f422c2635cab784a5e133538e4bb9
+dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=ca560c4fe28051573d54f512652ac9740a2d1111aeb8e36b004a6ff9c325925c
+dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=1191f15bb6da98b01b43f0e9d7f51c5c45d38e3c5be2b4ae5f7c0c8fd25e9a90
+dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5f85829aaab919fa4b2fa5ac843b87358e8da4797adbb6eeaed5be02666ce964
+dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=7c671d366fec561f0b568bfb4b6a08a6071303077a60f76da1307453e51ebc36
+dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=300307ab6cf88afc4312edaa510769e901598492deec4834176c6fc9f3eef6cb
+dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=6fcf91c8679f4963f7d510cc8afbc24a1070b25ea6d20d5d31ad78ea659da194
+dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=ab905f6f3119648c83a2f37ebe1a55b7899a5ac6d10070e4dbbfb89762a369af
+dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=13688b6857c8b10f7fb497f07c969d406cb6b76869957b5138f4b20fcc5d7c5a
+dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.gz=e6bb782014e34fafdc5dcf3aeb407eb636d822d346c5a8c6227cc45bc645561a
+dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.xz=6016ae620deddc42d1d6b6134b0164dab45a204089754b73db41ec837aa88a84
+dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ed3a381858612e25cacfd89c08496e9d06378d593ccedea4217ad4fa1ab326d4
+dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=4819bb9c25aa743de7ab7e93b10b30336a87f1f75e5122d578df2c83fbc59850
+dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=404aac87c77871c80f83cd7c59390af9af704ee468f40eba68d224d23e2c84e9
+dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=0e1e0d2454ad24fe1da2cce2dce425bc1167bbca68832da2476c7996c00ba612
+dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.gz=946d5bcc3ac0b83fd0b53b60290a6361b179f16ba2aa6a2467789ad520278792
+dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f3bd1a053399ec89dccaa7456da41d54a8e91deb5c628e4c502fdcf34c5fe780
+dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.gz=c353588a38705b7ae050d4b9868b6c4d3527295edbfb25c115b22cda4912be1f
+dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.xz=a71d8b2b42f6cd522da237f99492ed59cd34ea8c86fc1e73c8854c8234e1c980
+dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=5116b949572fd6c7b11a079d9453b15a4c48562bce22b26d82b7050da772789b
+dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=3635df40363273d44c6f8182f5f6a3a099ed55897bb764cab2565363cd31c1f4
+dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=5233af0b907fb7b176d2b5fee07c486e92dcbbbab1d54a60d814a827befaa984
+dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c908cad6d28657f1fdcbe9d84ecb86f247c75134803dd5273ca24c6c68a58f37
+dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c799165c319218a2fb4cdc0ac8db87fc9e2992a8e402d984ea27938a5ad1c5af
+dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.xz=ec12763fa5d4cc150f663361cd245c30835e05e3b1928898b1b7300de559468c
\ No newline at end of file
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 4c39aaff66862cc0da52fe529aa1990bb8bb9a2
+Subproject 20a443231846b81c7b909691ec3f15eb173f2b1
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index dd3124ee9a3..61efaa3bf3e 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,56 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[0f8eabd6...master](https://github.com/rust-lang/rust-clippy/compare/0f8eabd6...master)
+[aa0d5513...master](https://github.com/rust-lang/rust-clippy/compare/aa0d5513...master)
+
+## Rust 1.83
+
+Current stable, released 2024-11-28
+
+[View all 64 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-08-25T09%3A59%3A01Z..2024-10-03T13%3A42%3A56Z+base%3Amaster)
+
+### Important Change
+
+* Removed the implicit `cargo-clippy` feature set by Clippy as announced here:
+  <https://blog.rust-lang.org/2024/02/28/Clippy-deprecating-feature-cargo-clippy.html>
+  [#13246](https://github.com/rust-lang/rust-clippy/pull/13246)
+
+### New Lints
+
+* Added [`unused_trait_names`] to `restriction`
+  [#13322](https://github.com/rust-lang/rust-clippy/pull/13322)
+* Added [`unnecessary_first_then_check`] to `complexity`
+  [#13421](https://github.com/rust-lang/rust-clippy/pull/13421)
+* Added [`non_zero_suggestions`] to `restriction`
+  [#13167](https://github.com/rust-lang/rust-clippy/pull/13167)
+* Added [`manual_is_power_of_two`] to `pedantic`
+  [#13327](https://github.com/rust-lang/rust-clippy/pull/13327)
+* Added [`manual_div_ceil`] to `complexity`
+  [#12987](https://github.com/rust-lang/rust-clippy/pull/12987)
+* Added [`zombie_processes`] to `suspicious`
+  [#11476](https://github.com/rust-lang/rust-clippy/pull/11476)
+* Added [`used_underscore_items`] to `pedantic`
+  [#13294](https://github.com/rust-lang/rust-clippy/pull/13294)
+
+### Moves and Deprecations
+
+* Moved [`ref_option`] to `pedantic` (From `nursery`)
+  [#13469](https://github.com/rust-lang/rust-clippy/pull/13469)
+* Moved [`manual_c_str_literals`] to `complexity` (From `pedantic`, now warn-by-default)
+  [#13263](https://github.com/rust-lang/rust-clippy/pull/13263)
+* Moved [`empty_line_after_doc_comments`] to `suspicious` (From `nursery`, now warn-by-default)
+  [#13091](https://github.com/rust-lang/rust-clippy/pull/13091)
+* Moved [`empty_line_after_outer_attr`] to `suspicious` (From `nursery`, now warn-by-default)
+  [#13091](https://github.com/rust-lang/rust-clippy/pull/13091)
+
+### Enhancements
+
+* [`missing_panics_doc`]: No longer lints in const environments
+  [#13382](https://github.com/rust-lang/rust-clippy/pull/13382)
 
 ## Rust 1.82
 
-Current stable, released 2024-10-17
+Released 2024-10-17
 
 [View all 108 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-07-11T20%3A12%3A07Z..2024-08-24T20%3A55%3A35Z+base%3Amaster)
 
@@ -5441,6 +5486,7 @@ Released 2018-09-13
 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
 [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
+[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg
 [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
 [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
 [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 50a2afbfc07..77cb0006ff8 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,8 @@
 [package]
 name = "clippy"
-version = "0.1.84"
+# begin autogenerated version
+version = "0.1.85"
+# end autogenerated version
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -27,7 +29,7 @@ rustc_tools_util = "0.4.0"
 tempfile = { version = "3.3", optional = true }
 termize = "0.1"
 color-print = "0.3.4"
-anstream = "0.6.0"
+anstream = "0.6.18"
 
 [dev-dependencies]
 cargo_metadata = "0.18.1"
diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index be13fcbe260..19328fdd3cd 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -7,6 +7,7 @@
 - [Configuration](configuration.md)
     - [Lint Configuration](lint_configuration.md)
 - [Clippy's Lints](lints.md)
+- [Attributes for Crate Authors](attribs.md)
 - [Continuous Integration](continuous_integration/README.md)
     - [GitHub Actions](continuous_integration/github_actions.md)
     - [GitLab CI](continuous_integration/gitlab.md)
diff --git a/src/tools/clippy/book/src/attribs.md b/src/tools/clippy/book/src/attribs.md
new file mode 100644
index 00000000000..cf99497bc0f
--- /dev/null
+++ b/src/tools/clippy/book/src/attribs.md
@@ -0,0 +1,53 @@
+# Attributes for Crate Authors
+
+In some cases it is possible to extend Clippy coverage to 3rd party libraries.
+To do this, Clippy provides attributes that can be applied to items in the 3rd party crate.
+
+## `#[clippy::format_args]`
+
+_Available since Clippy v1.84_
+
+This attribute can be added to a macro that supports `format!`, `println!`, or similar syntax.
+It tells Clippy that the macro is a formatting macro, and that the arguments to the macro
+should be linted as if they were arguments to `format!`. Any lint that would apply to a
+`format!` call will also apply to the macro call. The macro may have additional arguments
+before the format string, and these will be ignored.
+
+### Example
+
+```rust
+/// A macro that prints a message if a condition is true.
+#[macro_export]
+#[clippy::format_args]
+macro_rules! print_if {
+    ($condition:expr, $($args:tt)+) => {{
+        if $condition {
+            println!($($args)+)
+        }
+    }};
+}
+```
+
+## `#[clippy::has_significant_drop]`
+
+_Available since Clippy v1.60_
+
+The `clippy::has_significant_drop` attribute can be added to types whose Drop impls have an important side effect,
+such as unlocking a mutex, making it important for users to be able to accurately understand their lifetimes.
+When a temporary is returned in a function call in a match scrutinee, its lifetime lasts until the end of the match
+block, which may be surprising.
+
+### Example
+
+```rust
+#[clippy::has_significant_drop]
+struct CounterWrapper<'a> {
+    counter: &'a Counter,
+}
+
+impl<'a> Drop for CounterWrapper<'a> {
+    fn drop(&mut self) {
+        self.counter.i.fetch_sub(1, Ordering::Relaxed);
+    }
+}
+```
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index 963e02e5c16..c07568697d0 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -438,7 +438,7 @@ need to ensure that the MSRV configured for the project is >= the MSRV of the
 required Rust feature. If multiple features are required, just use the one with
 a lower MSRV.
 
-First, add an MSRV alias for the required feature in [`clippy_config::msrvs`].
+First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`].
 This can be accessed later as `msrvs::STR_STRIP_PREFIX`, for example.
 
 ```rust
@@ -517,7 +517,7 @@ define_Conf! {
 }
 ```
 
-[`clippy_config::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html
+[`clippy_utils::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html
 
 Afterwards update the documentation for the book as described in [Adding configuration to a lint](#adding-configuration-to-a-lint).
 
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 670b5cbef82..275d125096e 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -895,7 +895,7 @@ The order of associated items in traits.
 
 ## `trivial-copy-size-limit`
 The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
-reference. By default there is no limit
+reference.
 
 **Default Value:** `target_pointer_width * 2`
 
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index d21df202dca..3f18a0bc7d2 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,11 +1,15 @@
 [package]
 name = "clippy_config"
-version = "0.1.84"
+# begin autogenerated version
+version = "0.1.85"
+# end autogenerated version
 edition = "2021"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+clippy_utils = { path = "../clippy_utils" }
 itertools = "0.12"
 serde = { version = "1.0", features = ["derive"] }
 toml = "0.7.3"
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 600d5b6e2c8..41b56b45d9a 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -1,10 +1,10 @@
 use crate::ClippyConfiguration;
-use crate::msrvs::Msrv;
 use crate::types::{
     DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering,
     SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind,
     SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds,
 };
+use clippy_utils::msrvs::Msrv;
 use rustc_errors::Applicability;
 use rustc_session::Session;
 use rustc_span::edit_distance::edit_distance;
@@ -181,7 +181,7 @@ macro_rules! define_Conf {
     )*) => {
         /// Clippy lint configuration
         pub struct Conf {
-            $($(#[doc = $doc])+ pub $name: $ty,)*
+            $($(#[cfg_attr(doc, doc = $doc)])+ pub $name: $ty,)*
         }
 
         mod defaults {
@@ -678,7 +678,7 @@ define_Conf! {
     #[lints(arbitrary_source_item_ordering)]
     trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(),
     /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
-    /// reference. By default there is no limit
+    /// reference.
     #[default_text = "target_pointer_width * 2"]
     #[lints(trivially_copy_pass_by_ref)]
     trivial_copy_size_limit: Option<u64> = None,
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index 1c3f32c2514..5d6e8b87516 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -13,18 +13,14 @@
     rustc::untranslatable_diagnostic
 )]
 
-extern crate rustc_ast;
-extern crate rustc_attr;
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
 extern crate rustc_errors;
+extern crate rustc_hir;
+extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
-extern crate smallvec;
 
 mod conf;
 mod metadata;
-pub mod msrvs;
 pub mod types;
 
 pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation};
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index fe576424148..c949db9109d 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -1,3 +1,6 @@
+use clippy_utils::def_path_def_ids;
+use rustc_hir::def_id::DefIdMap;
+use rustc_middle::ty::TyCtxt;
 use serde::de::{self, Deserializer, Visitor};
 use serde::{Deserialize, Serialize, ser};
 use std::collections::HashMap;
@@ -31,6 +34,18 @@ impl DisallowedPath {
     }
 }
 
+/// Creates a map of disallowed items to the reason they were disallowed.
+pub fn create_disallowed_map(
+    tcx: TyCtxt<'_>,
+    disallowed: &'static [DisallowedPath],
+) -> DefIdMap<(&'static str, Option<&'static str>)> {
+    disallowed
+        .iter()
+        .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x.reason()))
+        .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason))))
+        .collect()
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
 pub enum MatchLintBehaviour {
     AllTypes,
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 952a8711fb4..d3a103eaf4c 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 
 [dependencies]
 aho-corasick = "1.0"
+chrono = { version = "0.4.38", default-features = false, features = ["clock"] }
 clap = { version = "4.4", features = ["derive"] }
 indoc = "1.0"
 itertools = "0.12"
diff --git a/src/tools/clippy/clippy_dev/src/dogfood.rs b/src/tools/clippy/clippy_dev/src/dogfood.rs
index a0d57f5ab48..75a4cbd2f92 100644
--- a/src/tools/clippy/clippy_dev/src/dogfood.rs
+++ b/src/tools/clippy/clippy_dev/src/dogfood.rs
@@ -1,4 +1,4 @@
-use crate::{clippy_project_root, exit_if_err};
+use crate::utils::{clippy_project_root, exit_if_err};
 use std::process::Command;
 
 /// # Panics
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 8c61c35533c..c6673859282 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -1,4 +1,4 @@
-use crate::clippy_project_root;
+use crate::utils::clippy_project_root;
 use itertools::Itertools;
 use rustc_lexer::{TokenKind, tokenize};
 use shell_escape::escape;
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index ad385d5fbd2..9280369c23b 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -14,69 +14,13 @@
 extern crate rustc_driver;
 extern crate rustc_lexer;
 
-use std::io;
-use std::path::PathBuf;
-use std::process::{self, ExitStatus};
-
 pub mod dogfood;
 pub mod fmt;
 pub mod lint;
 pub mod new_lint;
+pub mod release;
 pub mod serve;
 pub mod setup;
+pub mod sync;
 pub mod update_lints;
-
-#[cfg(not(windows))]
-static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
-#[cfg(windows)]
-static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
-
-/// Returns the path to the `cargo-clippy` binary
-///
-/// # Panics
-///
-/// Panics if the path of current executable could not be retrieved.
-#[must_use]
-pub fn cargo_clippy_path() -> PathBuf {
-    let mut path = std::env::current_exe().expect("failed to get current executable name");
-    path.set_file_name(CARGO_CLIPPY_EXE);
-    path
-}
-
-/// Returns the path to the Clippy project directory
-///
-/// # Panics
-///
-/// Panics if the current directory could not be retrieved, there was an error reading any of the
-/// Cargo.toml files or ancestor directory is the clippy root directory
-#[must_use]
-pub fn clippy_project_root() -> PathBuf {
-    let current_dir = std::env::current_dir().unwrap();
-    for path in current_dir.ancestors() {
-        let result = std::fs::read_to_string(path.join("Cargo.toml"));
-        if let Err(err) = &result {
-            if err.kind() == io::ErrorKind::NotFound {
-                continue;
-            }
-        }
-
-        let content = result.unwrap();
-        if content.contains("[package]\nname = \"clippy\"") {
-            return path.to_path_buf();
-        }
-    }
-    panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
-}
-
-/// # Panics
-/// Panics if given command result was failed.
-pub fn exit_if_err(status: io::Result<ExitStatus>) {
-    match status.expect("failed to run command").code() {
-        Some(0) => {},
-        Some(n) => process::exit(n),
-        None => {
-            eprintln!("Killed by signal");
-            process::exit(1);
-        },
-    }
-}
+pub mod utils;
diff --git a/src/tools/clippy/clippy_dev/src/lint.rs b/src/tools/clippy/clippy_dev/src/lint.rs
index f308f5dfdfd..125195397e6 100644
--- a/src/tools/clippy/clippy_dev/src/lint.rs
+++ b/src/tools/clippy/clippy_dev/src/lint.rs
@@ -1,4 +1,4 @@
-use crate::{cargo_clippy_path, exit_if_err};
+use crate::utils::{cargo_clippy_path, exit_if_err};
 use std::process::{self, Command};
 use std::{env, fs};
 
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index fc15913354c..56ed60256f1 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -3,7 +3,7 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
 use clap::{Args, Parser, Subcommand};
-use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints};
+use clippy_dev::{dogfood, fmt, lint, new_lint, release, serve, setup, sync, update_lints, utils};
 use std::convert::Infallible;
 
 fn main() {
@@ -23,9 +23,9 @@ fn main() {
             if print_only {
                 update_lints::print_lints();
             } else if check {
-                update_lints::update(update_lints::UpdateMode::Check);
+                update_lints::update(utils::UpdateMode::Check);
             } else {
-                update_lints::update(update_lints::UpdateMode::Change);
+                update_lints::update(utils::UpdateMode::Change);
             }
         },
         DevCommand::NewLint {
@@ -35,7 +35,7 @@ fn main() {
             r#type,
             msrv,
         } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) {
-            Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
+            Ok(()) => update_lints::update(utils::UpdateMode::Change),
             Err(e) => eprintln!("Unable to create lint: {e}"),
         },
         DevCommand::Setup(SetupCommand { subcommand }) => match subcommand {
@@ -75,6 +75,12 @@ fn main() {
             uplift,
         } => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift),
         DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, &reason),
+        DevCommand::Sync(SyncCommand { subcommand }) => match subcommand {
+            SyncSubcommand::UpdateNightly => sync::update_nightly(),
+        },
+        DevCommand::Release(ReleaseCommand { subcommand }) => match subcommand {
+            ReleaseSubcommand::BumpVersion => release::bump_version(),
+        },
     }
 }
 
@@ -225,6 +231,10 @@ enum DevCommand {
         /// The reason for deprecation
         reason: String,
     },
+    /// Sync between the rust repo and the Clippy repo
+    Sync(SyncCommand),
+    /// Manage Clippy releases
+    Release(ReleaseCommand),
 }
 
 #[derive(Args)]
@@ -291,3 +301,29 @@ enum RemoveSubcommand {
     /// Remove the tasks added with 'cargo dev setup vscode-tasks'
     VscodeTasks,
 }
+
+#[derive(Args)]
+struct SyncCommand {
+    #[command(subcommand)]
+    subcommand: SyncSubcommand,
+}
+
+#[derive(Subcommand)]
+enum SyncSubcommand {
+    #[command(name = "update_nightly")]
+    /// Update nightly version in rust-toolchain and `clippy_utils`
+    UpdateNightly,
+}
+
+#[derive(Args)]
+struct ReleaseCommand {
+    #[command(subcommand)]
+    subcommand: ReleaseSubcommand,
+}
+
+#[derive(Subcommand)]
+enum ReleaseSubcommand {
+    #[command(name = "bump_version")]
+    /// Bump the version in the Cargo.toml files
+    BumpVersion,
+}
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index e15ba339717..24d1a53266a 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -1,4 +1,4 @@
-use crate::clippy_project_root;
+use crate::utils::{clippy_project_root, clippy_version};
 use indoc::{formatdoc, writedoc};
 use std::fmt;
 use std::fmt::Write as _;
@@ -186,23 +186,8 @@ fn to_camel_case(name: &str) -> String {
 }
 
 pub(crate) fn get_stabilization_version() -> String {
-    fn parse_manifest(contents: &str) -> Option<String> {
-        let version = contents
-            .lines()
-            .filter_map(|l| l.split_once('='))
-            .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?;
-        let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else {
-            return None;
-        };
-        let (minor, patch) = version.split_once('.')?;
-        Some(format!(
-            "{}.{}.0",
-            minor.parse::<u32>().ok()?,
-            patch.parse::<u32>().ok()?
-        ))
-    }
-    let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`");
-    parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`")
+    let (minor, patch) = clippy_version();
+    format!("{minor}.{patch}.0")
 }
 
 fn get_test_file_contents(lint_name: &str, msrv: bool) -> String {
@@ -273,7 +258,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
     result.push_str(&if enable_msrv {
         formatdoc!(
             r"
-            use clippy_config::msrvs::{{self, Msrv}};
+            use clippy_utils::msrvs::{{self, Msrv}};
             use clippy_config::Conf;
             {pass_import}
             use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
@@ -399,7 +384,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
         let _: fmt::Result = writedoc!(
             lint_file_contents,
             r#"
-                use clippy_config::msrvs::{{self, Msrv}};
+                use clippy_utils::msrvs::{{self, Msrv}};
                 use rustc_lint::{{{context_import}, LintContext}};
 
                 use super::{name_upper};
diff --git a/src/tools/clippy/clippy_dev/src/release.rs b/src/tools/clippy/clippy_dev/src/release.rs
new file mode 100644
index 00000000000..ac755168701
--- /dev/null
+++ b/src/tools/clippy/clippy_dev/src/release.rs
@@ -0,0 +1,27 @@
+use std::fmt::Write;
+use std::path::Path;
+
+use crate::utils::{UpdateMode, clippy_version, replace_region_in_file};
+
+const CARGO_TOML_FILES: [&str; 4] = [
+    "clippy_config/Cargo.toml",
+    "clippy_lints/Cargo.toml",
+    "clippy_utils/Cargo.toml",
+    "Cargo.toml",
+];
+
+pub fn bump_version() {
+    let (minor, mut patch) = clippy_version();
+    patch += 1;
+    for file in &CARGO_TOML_FILES {
+        replace_region_in_file(
+            UpdateMode::Change,
+            Path::new(file),
+            "# begin autogenerated version\n",
+            "# end autogenerated version",
+            |res| {
+                writeln!(res, "version = \"0.{minor}.{patch}\"").unwrap();
+            },
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_dev/src/sync.rs b/src/tools/clippy/clippy_dev/src/sync.rs
new file mode 100644
index 00000000000..3522d182e90
--- /dev/null
+++ b/src/tools/clippy/clippy_dev/src/sync.rs
@@ -0,0 +1,33 @@
+use std::fmt::Write;
+use std::path::Path;
+
+use chrono::offset::Utc;
+
+use crate::utils::{UpdateMode, replace_region_in_file};
+
+pub fn update_nightly() {
+    // Update rust-toolchain nightly version
+    let date = Utc::now().format("%Y-%m-%d").to_string();
+    replace_region_in_file(
+        UpdateMode::Change,
+        Path::new("rust-toolchain"),
+        "# begin autogenerated nightly\n",
+        "# end autogenerated nightly",
+        |res| {
+            writeln!(res, "channel = \"nightly-{date}\"").unwrap();
+        },
+    );
+
+    // Update clippy_utils nightly version
+    replace_region_in_file(
+        UpdateMode::Change,
+        Path::new("clippy_utils/README.md"),
+        "<!-- begin autogenerated nightly -->\n",
+        "<!-- end autogenerated nightly -->",
+        |res| {
+            writeln!(res, "```").unwrap();
+            writeln!(res, "nightly-{date}").unwrap();
+            writeln!(res, "```").unwrap();
+        },
+    );
+}
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 795456ad3c5..612d1c0ae13 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,4 +1,4 @@
-use crate::clippy_project_root;
+use crate::utils::{UpdateMode, clippy_project_root, exit_with_failure, replace_region_in_file};
 use aho_corasick::AhoCorasickBuilder;
 use itertools::Itertools;
 use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape};
@@ -17,12 +17,6 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u
 
 const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
 
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub enum UpdateMode {
-    Check,
-    Change,
-}
-
 /// Runs the `update_lints` command.
 ///
 /// This updates various generated values from the lint source code.
@@ -511,14 +505,6 @@ fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str)
     }
 }
 
-fn exit_with_failure() {
-    println!(
-        "Not all lints defined properly. \
-                 Please run `cargo dev update_lints` to make sure all lints are defined properly."
-    );
-    std::process::exit(1);
-}
-
 /// Lint data parsed from the Clippy source code.
 #[derive(Clone, PartialEq, Eq, Debug)]
 struct Lint {
@@ -851,61 +837,6 @@ fn remove_line_splices(s: &str) -> String {
     });
     res
 }
-
-/// Replaces a region in a file delimited by two lines matching regexes.
-///
-/// `path` is the relative path to the file on which you want to perform the replacement.
-///
-/// See `replace_region_in_text` for documentation of the other options.
-///
-/// # Panics
-///
-/// Panics if the path could not read or then written
-fn replace_region_in_file(
-    update_mode: UpdateMode,
-    path: &Path,
-    start: &str,
-    end: &str,
-    write_replacement: impl FnMut(&mut String),
-) {
-    let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
-    let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) {
-        Ok(x) => x,
-        Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()),
-    };
-
-    match update_mode {
-        UpdateMode::Check if contents != new_contents => exit_with_failure(),
-        UpdateMode::Check => (),
-        UpdateMode::Change => {
-            if let Err(e) = fs::write(path, new_contents.as_bytes()) {
-                panic!("Cannot write to `{}`: {e}", path.display());
-            }
-        },
-    }
-}
-
-/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters
-/// were found, or the missing delimiter if not.
-fn replace_region_in_text<'a>(
-    text: &str,
-    start: &'a str,
-    end: &'a str,
-    mut write_replacement: impl FnMut(&mut String),
-) -> Result<String, &'a str> {
-    let (text_start, rest) = text.split_once(start).ok_or(start)?;
-    let (_, text_end) = rest.split_once(end).ok_or(end)?;
-
-    let mut res = String::with_capacity(text.len() + 4096);
-    res.push_str(text_start);
-    res.push_str(start);
-    write_replacement(&mut res);
-    res.push_str(end);
-    res.push_str(text_end);
-
-    Ok(res)
-}
-
 fn try_rename_file(old_name: &Path, new_name: &Path) -> bool {
     match OpenOptions::new().create_new(true).write(true).open(new_name) {
         Ok(file) => drop(file),
diff --git a/src/tools/clippy/clippy_dev/src/utils.rs b/src/tools/clippy/clippy_dev/src/utils.rs
new file mode 100644
index 00000000000..b87fcca13b1
--- /dev/null
+++ b/src/tools/clippy/clippy_dev/src/utils.rs
@@ -0,0 +1,142 @@
+use std::path::{Path, PathBuf};
+use std::process::{self, ExitStatus};
+use std::{fs, io};
+
+#[cfg(not(windows))]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
+#[cfg(windows)]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
+
+/// Returns the path to the `cargo-clippy` binary
+///
+/// # Panics
+///
+/// Panics if the path of current executable could not be retrieved.
+#[must_use]
+pub fn cargo_clippy_path() -> PathBuf {
+    let mut path = std::env::current_exe().expect("failed to get current executable name");
+    path.set_file_name(CARGO_CLIPPY_EXE);
+    path
+}
+
+/// Returns the path to the Clippy project directory
+///
+/// # Panics
+///
+/// Panics if the current directory could not be retrieved, there was an error reading any of the
+/// Cargo.toml files or ancestor directory is the clippy root directory
+#[must_use]
+pub fn clippy_project_root() -> PathBuf {
+    let current_dir = std::env::current_dir().unwrap();
+    for path in current_dir.ancestors() {
+        let result = fs::read_to_string(path.join("Cargo.toml"));
+        if let Err(err) = &result {
+            if err.kind() == io::ErrorKind::NotFound {
+                continue;
+            }
+        }
+
+        let content = result.unwrap();
+        if content.contains("[package]\nname = \"clippy\"") {
+            return path.to_path_buf();
+        }
+    }
+    panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
+}
+
+/// # Panics
+/// Panics if given command result was failed.
+pub fn exit_if_err(status: io::Result<ExitStatus>) {
+    match status.expect("failed to run command").code() {
+        Some(0) => {},
+        Some(n) => process::exit(n),
+        None => {
+            eprintln!("Killed by signal");
+            process::exit(1);
+        },
+    }
+}
+
+pub(crate) fn clippy_version() -> (u32, u32) {
+    fn parse_manifest(contents: &str) -> Option<(u32, u32)> {
+        let version = contents
+            .lines()
+            .filter_map(|l| l.split_once('='))
+            .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?;
+        let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else {
+            return None;
+        };
+        let (minor, patch) = version.split_once('.')?;
+        Some((minor.parse().ok()?, patch.parse().ok()?))
+    }
+    let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`");
+    parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`")
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum UpdateMode {
+    Check,
+    Change,
+}
+
+pub(crate) fn exit_with_failure() {
+    println!(
+        "Not all lints defined properly. \
+                 Please run `cargo dev update_lints` to make sure all lints are defined properly."
+    );
+    process::exit(1);
+}
+
+/// Replaces a region in a file delimited by two lines matching regexes.
+///
+/// `path` is the relative path to the file on which you want to perform the replacement.
+///
+/// See `replace_region_in_text` for documentation of the other options.
+///
+/// # Panics
+///
+/// Panics if the path could not read or then written
+pub(crate) fn replace_region_in_file(
+    update_mode: UpdateMode,
+    path: &Path,
+    start: &str,
+    end: &str,
+    write_replacement: impl FnMut(&mut String),
+) {
+    let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
+    let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) {
+        Ok(x) => x,
+        Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()),
+    };
+
+    match update_mode {
+        UpdateMode::Check if contents != new_contents => exit_with_failure(),
+        UpdateMode::Check => (),
+        UpdateMode::Change => {
+            if let Err(e) = fs::write(path, new_contents.as_bytes()) {
+                panic!("Cannot write to `{}`: {e}", path.display());
+            }
+        },
+    }
+}
+
+/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters
+/// were found, or the missing delimiter if not.
+pub(crate) fn replace_region_in_text<'a>(
+    text: &str,
+    start: &'a str,
+    end: &'a str,
+    mut write_replacement: impl FnMut(&mut String),
+) -> Result<String, &'a str> {
+    let (text_start, rest) = text.split_once(start).ok_or(start)?;
+    let (_, text_end) = rest.split_once(end).ok_or(end)?;
+
+    let mut res = String::with_capacity(text.len() + 4096);
+    res.push_str(text_start);
+    res.push_str(start);
+    write_replacement(&mut res);
+    res.push_str(end);
+    res.push_str(text_end);
+
+    Ok(res)
+}
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 63ea6faf60d..c1f8e82f698 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,8 @@
 [package]
 name = "clippy_lints"
-version = "0.1.84"
+# begin autogenerated version
+version = "0.1.85"
+# end autogenerated version
 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/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
index 370f0c482fd..2af5178920d 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{trim_span, walk_span_to_context};
 use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 4f8f091a095..ebd35fd2b27 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -91,7 +91,7 @@ impl ApproxConstant {
         let s = s.as_str();
         if s.parse::<f64>().is_ok() {
             for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
-                if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| self.msrv.meets(msrv)) {
+                if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(msrv)) {
                     span_lint_and_help(
                         cx,
                         APPROX_CONSTANT,
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index 00626a37ef8..c8dd77d9578 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
 use rustc_errors::Applicability;
@@ -100,13 +100,13 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
             // TODO: This check currently bails if the local variable has no initializer.
             // That is overly conservative - the lint should fire even if there was no initializer,
             // but the variable has been initialized before `lhs` was evaluated.
-            && path_to_local(lhs).map_or(true, |lhs| local_is_initialized(cx, lhs))
+            && path_to_local(lhs).is_none_or(|lhs| local_is_initialized(cx, lhs))
             && let Some(resolved_impl) = cx.tcx.impl_of_method(resolved_fn.def_id())
             // Derived forms don't implement `clone_from`/`clone_into`.
             // See https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305
             && !cx.tcx.is_builtin_derived(resolved_impl)
             // Don't suggest calling a function we're implementing.
-            && resolved_impl.as_local().map_or(true, |block_id| {
+            && resolved_impl.as_local().is_none_or(|block_id| {
                 cx.tcx.hir().parent_owner_iter(e.hir_id).all(|(id, _)| id.def_id != block_id)
             })
             && let resolved_assoc_items = cx.tcx.associated_items(resolved_impl)
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
index abf924f7542..3a462018e3e 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
@@ -1,6 +1,6 @@
 use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg};
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::AttrStyle;
 use rustc_errors::Applicability;
 use rustc_lint::EarlyContext;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index c29c9f08cf7..a9766597d50 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -13,7 +13,7 @@ mod useless_attribute;
 mod utils;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
 use rustc_hir::{ImplItem, Item, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
index fadd5272880..97cffeb098e 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
@@ -9,7 +9,7 @@ use rustc_span::sym;
 
 pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
     if let AttrKind::Normal(normal_attr) = &attr.kind {
-        if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
+        if let AttrArgs::Eq { value:  AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
             // `#[should_panic = ".."]` found, good
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 6948cf560a5..2eb0566bf9a 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,6 +1,7 @@
 use clippy_config::Conf;
+use clippy_config::types::create_disallowed_map;
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{create_disallowed_map, match_def_path, paths};
+use clippy_utils::{match_def_path, paths};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 896bd5fd03d..6eef0d42a55 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::eq_expr_value;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_ast::ast::LitKind;
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index f2551a05b1a..8892a9e6b6b 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
             && !addrof_target.span.from_expansion()
             && let ref_ty = cx.typeck_results().expr_ty(deref_target)
             && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
-            && get_parent_expr(cx, e).map_or(true, |parent| {
+            && get_parent_expr(cx, e).is_none_or(|parent| {
                 match parent.kind {
                     // `*&*foo` should lint `deref_addrof` instead.
                     ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id),
diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
index 6714c053913..80514cb52e6 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
@@ -43,7 +43,7 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel
 }
 
 fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: Option<&T>) -> bool {
-    value.map_or(true, |s| s.as_ref().is_empty())
+    value.is_none_or(|s| s.as_ref().is_empty())
 }
 
 fn is_empty_vec(value: &[String]) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
index b7b63250864..ae433773193 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
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 84a44b14dde..4ad39d9160d 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_const_context;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_isize_or_usize;
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 40a1a9d1ce8..48e9f1d690e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -134,7 +134,7 @@ pub(super) fn check(
             };
             let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
 
-            let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),));
+            let cast_from_ptr_size = def.repr().int.is_none_or(|ty| matches!(ty, IntegerType::Pointer(_),));
             let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
                 (_, false) if from_nbits > to_nbits => "",
                 (false, true) if from_nbits > 64 => "",
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index 285f0357112..030c2d322db 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source;
 use rustc_ast::Mutability;
 use rustc_hir::{Expr, ExprKind, Node};
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
index 1d89f6c75e1..c3bc5c0c9f2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 3acd4eca420..8b884399f92 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -24,8 +24,8 @@ mod utils;
 mod zero_ptr;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::is_hir_ty_cfg_dependant;
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 46d67e615c7..a138ade54aa 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
index 7518dd2435a..945c05ee943 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::std_or_core;
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index f76e399517c..364f5c7dc7a 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 3ecd36d3711..89808d38b9f 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -212,7 +212,7 @@ fn lint_if_same_then_else(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[&
         .array_windows::<2>()
         .enumerate()
         .fold(true, |all_eq, (i, &[lhs, rhs])| {
-            if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).map_or(true, |e| !contains_let(e)) {
+            if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).is_none_or(|e| !contains_let(e)) {
                 span_lint_and_note(
                     cx,
                     IF_SAME_THEN_ELSE,
@@ -470,7 +470,7 @@ fn scan_block_for_eq<'tcx>(
                 b.stmts
                     // the bounds check will catch the underflow
                     .get(b.stmts.len().wrapping_sub(offset + 1))
-                    .map_or(true, |s| hash != hash_stmt(cx, s))
+                    .is_none_or(|s| hash != hash_stmt(cx, s))
             })
         })
         .map_or(block.stmts.len() - start_end_eq, |(i, _)| i);
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index dff60f76b74..022ed180ed8 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -135,6 +135,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::disallowed_names::DISALLOWED_NAMES_INFO,
     crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
     crate::disallowed_types::DISALLOWED_TYPES_INFO,
+    crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO,
     crate::doc::DOC_LAZY_CONTINUATION_INFO,
     crate::doc::DOC_LINK_WITH_QUOTES_INFO,
     crate::doc::DOC_MARKDOWN_INFO,
@@ -743,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::unit_types::LET_UNIT_VALUE_INFO,
     crate::unit_types::UNIT_ARG_INFO,
     crate::unit_types::UNIT_CMP_INFO,
-    crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
     crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
     crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
     crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index de775b64795..ffdd946aadb 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -5,7 +5,7 @@ use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
+use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
@@ -285,7 +285,7 @@ fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Op
 /// Returns whether `expr` is the update syntax base: `Foo { a: 1, .. base }`
 fn is_update_syntax_base<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
     if let Some(parent) = get_parent_expr(cx, expr)
-        && let ExprKind::Struct(_, _, Some(base)) = parent.kind
+        && let ExprKind::Struct(_, _, StructTailExpr::Base(base)) = parent.kind
     {
         base.hir_id == expr.hir_id
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index ef6b141920d..6819ad547f8 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
-use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind};
+use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -197,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
                     }
 
                     // Visit base with no bound.
-                    if let Some(base) = base {
+                    if let StructTailExpr::Base(base) = base {
                         self.ty_bounds.push(ExplicitTyBound(false));
                         self.visit_expr(base);
                         self.ty_bounds.pop();
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 77dbe9b78a1..3ea792d8b83 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
     #[clippy::version = "1.53.0"]
     ("clippy::filter_map", "clippy::manual_filter_map"),
     #[clippy::version = ""]
+    ("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"),
+    #[clippy::version = ""]
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     #[clippy::version = "pre 1.29.0"]
     ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 1eebfc22af2..c449a1a875b 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -7,15 +7,15 @@ use clippy_utils::{
     peel_middle_ty_refs,
 };
 use core::mem;
-use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{Visitor, walk_ty};
 use rustc_hir::{
     self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat,
     PatKind, Path, QPath, TyKind, UnOp,
 };
-use rustc_hir::def_id::DefId;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
@@ -453,7 +453,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             ));
                         } else if stability.is_deref_stable()
                             // Auto-deref doesn't combine with other adjustments
-                            && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
+                            && next_adjust.is_none_or(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                             && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                         {
                             self.state = Some((State::Borrow { mutability }, StateData {
@@ -963,7 +963,7 @@ fn report<'tcx>(
             // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
             // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
             /*
-            expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX {
+            expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix {
                 Cow::Owned(format!("({expr_str})"))
             } else {
                 expr_str
@@ -999,13 +999,13 @@ fn report<'tcx>(
                 data.first_expr.span,
                 state.msg,
                 |diag| {
-                    let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
+                    let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
                         Node::Expr(e) => match e.kind {
-                            ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
-                            ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
-                            _ => (e.precedence(), false),
+                            ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
+                            ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)),
+                            _ => expr.precedence() < e.precedence(),
                         },
-                        _ => (0, false),
+                        _ => false,
                     };
                     let is_in_tuple = matches!(
                         get_parent_expr(cx, data.first_expr),
@@ -1016,7 +1016,7 @@ fn report<'tcx>(
                     );
 
                     let sugg = if !snip_is_macro
-                        && (calls_field || expr.precedence() < precedence)
+                        && needs_paren
                         && !has_enclosing_paren(&snip)
                         && !is_in_tuple
                     {
@@ -1049,16 +1049,16 @@ fn report<'tcx>(
                 }
             }
 
-            let (prefix, precedence) = match mutability {
+            let (prefix, needs_paren) = match mutability {
                 Some(mutability) if !ty.is_ref() => {
                     let prefix = match mutability {
                         Mutability::Not => "&",
                         Mutability::Mut => "&mut ",
                     };
-                    (prefix, PREC_PREFIX)
+                    (prefix, expr.precedence() < ExprPrecedence::Prefix)
                 },
-                None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
-                _ => ("", 0),
+                None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
+                _ => ("", false),
             };
             span_lint_hir_and_then(
                 cx,
@@ -1070,12 +1070,11 @@ fn report<'tcx>(
                     let mut app = Applicability::MachineApplicable;
                     let (snip, snip_is_macro) =
                         snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
-                    let sugg =
-                        if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) {
-                            format!("{prefix}({snip})")
-                        } else {
-                            format!("{prefix}{snip}")
-                        };
+                    let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) {
+                        format!("{prefix}({snip})")
+                    } else {
+                        format!("{prefix}{snip}")
+                    };
                     diag.span_suggestion(data.first_expr.span, "try", sugg, app);
                 },
             );
@@ -1158,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> {
                         },
                         Some(parent) if !parent.span.from_expansion() => {
                             // Double reference might be needed at this point.
-                            if parent.precedence() == PREC_UNAMBIGUOUS {
+                            if parent.precedence() == ExprPrecedence::Unambiguous {
                                 // Parentheses would be needed here, don't lint.
                                 *outer_pat = None;
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 767dda552bc..9569081ad08 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
 use rustc_errors::Applicability;
@@ -132,17 +132,15 @@ fn check_struct<'tcx>(
 
     if should_emit {
         let struct_span = cx.tcx.def_span(adt_def.did());
+        let suggestions = vec![
+            (item.span, String::new()), // Remove the manual implementation
+            (struct_span.shrink_to_lo(), "#[derive(Default)]\n".to_string()), // Add the derive attribute
+        ];
+
         span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
-            diag.span_suggestion_hidden(
-                item.span,
-                "remove the manual implementation...",
-                String::new(),
-                Applicability::MachineApplicable,
-            );
-            diag.span_suggestion(
-                struct_span.shrink_to_lo(),
-                "...and instead derive it",
-                "#[derive(Default)]\n".to_string(),
+            diag.multipart_suggestion(
+                "replace the manual implementation with a derive attribute",
+                suggestions,
                 Applicability::MachineApplicable,
             );
         });
@@ -161,23 +159,23 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex
         let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
         let variant_span = cx.tcx.def_span(variant_def.def_id);
         let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
-        span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
-            diag.span_suggestion_hidden(
-                item.span,
-                "remove the manual implementation...",
-                String::new(),
-                Applicability::MachineApplicable,
-            );
-            diag.span_suggestion(
+
+        let suggestions = vec![
+            (item.span, String::new()), // Remove the manual implementation
+            (
                 enum_span.shrink_to_lo(),
-                "...and instead derive it...",
-                format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),),
-                Applicability::MachineApplicable,
-            );
-            diag.span_suggestion(
+                format!("#[derive(Default)]\n{}", " ".repeat(indent_enum)),
+            ), // Add the derive attribute
+            (
                 variant_span.shrink_to_lo(),
-                "...and mark the default variant",
-                format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),),
+                format!("#[default]\n{}", " ".repeat(indent_variant)),
+            ), // Mark the default variant
+        ];
+
+        span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
+            diag.multipart_suggestion(
+                "replace the manual implementation with a derive attribute and mark the default variant",
+                suggestions,
                 Applicability::MachineApplicable,
             );
         });
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 1a34b87e42a..8125dab8adf 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -505,17 +505,15 @@ fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId
         }
     }
 
-    let param_env = ParamEnv::new(
-        tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
-            params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
-                ClauseKind::Trait(TraitPredicate {
-                    trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
-                    polarity: ty::PredicatePolarity::Positive,
-                })
-                .upcast(tcx)
-            }),
-        )),
-    );
+    let param_env = ParamEnv::new(tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
+        params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
+            ClauseKind::Trait(TraitPredicate {
+                trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
+                polarity: ty::PredicatePolarity::Positive,
+            })
+            .upcast(tcx)
+        }),
+    )));
     ty::TypingEnv {
         typing_mode: ty::TypingMode::non_body_analysis(),
         param_env,
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index bdd49bf8aa7..a0cb36f88dc 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -1,5 +1,5 @@
 use clippy_config::Conf;
-use clippy_utils::create_disallowed_map;
+use clippy_config::types::create_disallowed_map;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::macros::macro_backtrace;
 use rustc_data_structures::fx::FxHashSet;
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 5a01d76a2a6..1e660b1957a 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -1,5 +1,5 @@
 use clippy_config::Conf;
-use clippy_utils::create_disallowed_map;
+use clippy_config::types::create_disallowed_map;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs
new file mode 100644
index 00000000000..2182689f985
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs
@@ -0,0 +1,45 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute};
+use rustc_errors::Applicability;
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+use super::DOC_INCLUDE_WITHOUT_CFG;
+
+pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
+    for attr in attrs {
+        if !attr.span.from_expansion()
+            && let AttrKind::Normal(ref normal) = attr.kind
+            && normal.item.path == sym::doc
+            && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
+            && !attr.span.contains(meta.span)
+            // Since the `include_str` is already expanded at this point, we can only take the
+            // whole attribute snippet and then modify for our suggestion.
+            && let Some(snippet) = snippet_opt(cx, attr.span)
+            // We cannot remove this because a `#[doc = include_str!("...")]` attribute can occupy
+            // several lines.
+            && let Some(start) = snippet.find('[')
+            && let Some(end) = snippet.rfind(']')
+            && let snippet = &snippet[start + 1..end]
+            // We check that the expansion actually comes from `include_str!` and not just from
+            // another macro.
+            && let Some(sub_snippet) = snippet.trim().strip_prefix("doc")
+            && let Some(sub_snippet) = sub_snippet.trim().strip_prefix("=")
+            && sub_snippet.trim().starts_with("include_str!")
+        {
+            span_lint_and_sugg(
+                cx,
+                DOC_INCLUDE_WITHOUT_CFG,
+                attr.span,
+                "included a file in documentation unconditionally",
+                "use `cfg_attr(doc, doc = \"...\")`",
+                format!(
+                    "#{}[cfg_attr(doc, {snippet})]",
+                    if attr.style == AttrStyle::Inner { "!" } else { "" }
+                ),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index df7c37a192a..88ac871acf6 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::lint_without_lint_pass)]
+
 mod lazy_continuation;
 mod too_long_first_doc_paragraph;
 
@@ -33,6 +35,7 @@ use std::ops::Range;
 use url::Url;
 
 mod empty_line_after;
+mod include_in_doc_without_cfg;
 mod link_with_quotes;
 mod markdown;
 mod missing_headers;
@@ -532,6 +535,35 @@ declare_clippy_lint! {
     "empty line after doc comments"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if included files in doc comments are included only for `cfg(doc)`.
+    ///
+    /// ### Why restrict this?
+    /// These files are not useful for compilation but will still be included.
+    /// Also, if any of these non-source code file is updated, it will trigger a
+    /// recompilation.
+    ///
+    /// ### Known problems
+    ///
+    /// Excluding this will currently result in the file being left out if
+    /// the item's docs are inlined from another crate. This may be fixed in a
+    /// future version of rustdoc.
+    ///
+    /// ### Example
+    /// ```ignore
+    /// #![doc = include_str!("some_file.md")]
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #![cfg_attr(doc, doc = include_str!("some_file.md"))]
+    /// ```
+    #[clippy::version = "1.84.0"]
+    pub DOC_INCLUDE_WITHOUT_CFG,
+    restriction,
+    "check if files included in documentation are behind `cfg(doc)`"
+}
+
 pub struct Documentation {
     valid_idents: FxHashSet<String>,
     check_private_items: bool,
@@ -561,6 +593,7 @@ impl_lint_pass!(Documentation => [
     EMPTY_LINE_AFTER_OUTER_ATTR,
     EMPTY_LINE_AFTER_DOC_COMMENTS,
     TOO_LONG_FIRST_DOC_PARAGRAPH,
+    DOC_INCLUDE_WITHOUT_CFG,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Documentation {
@@ -690,6 +723,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
         Some(("fake".into(), "fake".into()))
     }
 
+    include_in_doc_without_cfg::check(cx, attrs);
     if suspicious_doc_comments::check(cx, attrs) || empty_line_after::check(cx, attrs) || is_doc_hidden(attrs) {
         return None;
     }
@@ -917,6 +951,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 }
                 let trimmed_text = text.trim();
                 headers.safety |= in_heading && trimmed_text == "Safety";
+                headers.safety |= in_heading && trimmed_text == "SAFETY";
                 headers.safety |= in_heading && trimmed_text == "Implementation safety";
                 headers.safety |= in_heading && trimmed_text == "Implementation Safety";
                 headers.errors |= in_heading && trimmed_text == "Errors";
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 6c87a05ace3..8c22e43349f 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -276,7 +276,7 @@ fn check_inputs(
             && typeck
                 .expr_adjustments(arg)
                 .last()
-                .map_or(true, |a| a.target == typeck.expr_ty(arg))
+                .is_none_or(|a| a.target == typeck.expr_ty(arg))
         })
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index c88fb50b5af..0011da03dda 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
             && fn_header.abi == Abi::Rust
             && fn_decl.inputs.len() as u64 > self.max_fn_params_bools
             && get_parent_as_impl(cx.tcx, cx.tcx.local_def_id_to_hir_id(def_id))
-                .map_or(true, |impl_item| impl_item.of_trait.is_none())
+                .is_none_or(|impl_item| impl_item.of_trait.is_none())
         {
             check_fn_decl(cx, fn_decl, span, self.max_fn_params_bools);
         }
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 81152da8c85..ae4b6680065 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty};
 use rustc_hir::{
     BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
-    PredicateOrigin, Ty, WherePredicate, WherePredicateKind
+    PredicateOrigin, Ty, WherePredicate, WherePredicateKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 4c043f8dc14..da5825b7ab2 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,6 +1,5 @@
 use arrayvec::ArrayVec;
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::macros::{
@@ -8,6 +7,7 @@ use clippy_utils::macros::{
     format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call,
     root_macro_call_first_node,
 };
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
 use itertools::Itertools;
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 14da0b515a5..e43c311eb85 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -1,9 +1,9 @@
 use std::ops::ControlFlow;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::span_is_local;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::path_def_id;
 use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
                 |diag| {
                     // If the target type is likely foreign mention the orphan rules as it's a common source of
                     // confusion
-                    if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) {
+                    if path_def_id(cx, target_ty.peel_refs()).is_none_or(|id| !id.is_local()) {
                         diag.help(
                             "`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\
                             https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence"
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index cf08c16458b..bb2dc9995df 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -1,3 +1,5 @@
+use std::ops::ControlFlow;
+
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::return_ty;
 use rustc_hir::intravisit::FnKind;
@@ -5,7 +7,9 @@ use rustc_hir::{Body, FnDecl};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::print::PrintTraitRefExt;
-use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
+use rustc_middle::ty::{
+    self, AliasTy, Binder, ClauseKind, PredicateKind, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, sym};
@@ -15,9 +19,16 @@ use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
 declare_clippy_lint! {
     /// ### What it does
     /// This lint requires Future implementations returned from
-    /// functions and methods to implement the `Send` marker trait. It is mostly
-    /// used by library authors (public and internal) that target an audience where
-    /// multithreaded executors are likely to be used for running these Futures.
+    /// functions and methods to implement the `Send` marker trait,
+    /// ignoring type parameters.
+    ///
+    /// If a function is generic and its Future conditionally implements `Send`
+    /// based on a generic parameter then it is considered `Send` and no warning is emitted.
+    ///
+    /// This can be used by library authors (public and internal) to ensure
+    /// their functions are compatible with both multi-threaded runtimes that require `Send` futures,
+    /// as well as single-threaded runtimes where callers may choose `!Send` types
+    /// for generic parameters.
     ///
     /// ### Why is this bad?
     /// A Future implementation captures some state that it
@@ -64,22 +75,46 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             return;
         }
         let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner());
-        if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() {
+        if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind()
+            && let Some(future_trait) = cx.tcx.lang_items().future_trait()
+            && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send)
+        {
             let preds = cx.tcx.explicit_item_super_predicates(def_id);
             let is_future = preds.iter_instantiated_copied(cx.tcx, args).any(|(p, _)| {
-                p.as_trait_clause().is_some_and(|trait_pred| {
-                    Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait()
-                })
+                p.as_trait_clause()
+                    .is_some_and(|trait_pred| trait_pred.skip_binder().trait_ref.def_id == future_trait)
             });
             if is_future {
-                let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
                 let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
                 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
                 let cause = traits::ObligationCause::misc(span, fn_def_id);
                 ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
                 let send_errors = ocx.select_all_or_error();
-                if !send_errors.is_empty() {
+
+                // Allow errors that try to prove `Send` for types that "mention" a generic parameter at the "top
+                // level".
+                // For example, allow errors that `T: Send` can't be proven, but reject `Rc<T>: Send` errors,
+                // which is always unconditionally `!Send` for any possible type `T`.
+                //
+                // We also allow associated type projections if the self type is either itself a projection or a
+                // type parameter.
+                // This is to prevent emitting warnings for e.g. holding a `<Fut as Future>::Output` across await
+                // points, where `Fut` is a type parameter.
+
+                let is_send = send_errors.iter().all(|err| {
+                    err.obligation
+                        .predicate
+                        .as_trait_clause()
+                        .map(Binder::skip_binder)
+                        .is_some_and(|pred| {
+                            pred.def_id() == send_trait
+                                && pred.self_ty().has_param()
+                                && TyParamAtTopLevelVisitor.visit_ty(pred.self_ty()) == ControlFlow::Break(true)
+                        })
+                });
+
+                if !is_send {
                     span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
@@ -107,3 +142,15 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
         }
     }
 }
+
+struct TyParamAtTopLevelVisitor;
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TyParamAtTopLevelVisitor {
+    type Result = ControlFlow<bool>;
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        match ty.kind() {
+            ty::Param(_) => ControlFlow::Break(true),
+            ty::Alias(ty::AliasTyKind::Projection, ty) => ty.visit_with(self),
+            _ => ControlFlow::Break(false),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index ba80c099a01..6444e99ae9c 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -7,6 +7,7 @@ use rustc_errors::Diag;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
+use rustc_span::edition::Edition::Edition2024;
 use rustc_span::sym;
 
 declare_clippy_lint! {
@@ -14,6 +15,12 @@ declare_clippy_lint! {
     /// Checks for `Mutex::lock` calls in `if let` expression
     /// with lock calls in any of the else blocks.
     ///
+    /// ### Disabled starting in Edition 2024
+    /// This lint is effectively disabled starting in
+    /// Edition 2024 as `if let ... else` scoping was reworked
+    /// such that this is no longer an issue. See
+    /// [Proposal: stabilize if_let_rescope for Edition 2024](https://github.com/rust-lang/rust/issues/131154)
+    ///
     /// ### Why is this bad?
     /// The Mutex lock remains held for the whole
     /// `if let ... else` block and deadlocks.
@@ -45,6 +52,10 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]);
 
 impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if cx.tcx.sess.edition() >= Edition2024 {
+            return;
+        }
+
         if let Some(higher::IfLet {
             let_expr,
             if_then,
@@ -86,7 +97,7 @@ fn mutex_lock_call<'tcx>(
         && path.ident.as_str() == "lock"
         && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
         && is_type_diagnostic_item(cx, ty, sym::Mutex)
-        && op_mutex.map_or(true, |op| eq_expr_value(cx, self_arg, op))
+        && op_mutex.is_none_or(|op| eq_expr_value(cx, self_arg, op))
     {
         ControlFlow::Break(self_arg)
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index d63c18c0eda..3fc0a696522 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 3b84b569c3e..37481dc7feb 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::{
     SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt,
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index 0b3a6ee1bea..f3467adacc5 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
+use clippy_utils::msrvs::Msrv;
 use rustc_attr::{StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind, HirId};
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index d386bfca6ba..4fcd2abb769 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -3,7 +3,7 @@ use clippy_utils::fulfill_or_allowed;
 use clippy_utils::source::snippet;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
-use rustc_hir::{self as hir, ExprKind};
+use rustc_hir::{self as hir, ExprKind, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
@@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
             }
             fields_snippet.push_str(&last_ident.to_string());
 
-            let base_snippet = if let Some(base) = base {
+            let base_snippet = if let StructTailExpr::Base(base) = base {
                 format!(", ..{}", snippet(cx, base.span, ".."))
             } else {
                 String::new()
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 96550c4d1cb..c2030a5ab09 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -1,8 +1,8 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 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};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
diff --git a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs
index 7f183bb601e..7a14bbfb9e8 100644
--- a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::SyntaxContext;
@@ -43,7 +43,7 @@ declare_lint_pass!(NumberedFields => [INIT_NUMBERED_FIELDS]);
 
 impl<'tcx> LateLintPass<'tcx> for NumberedFields {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Struct(path, fields @ [field, ..], None) = e.kind
+        if let ExprKind::Struct(path, fields @ [field, ..], StructTailExpr::None) = e.kind
             // If the first character of any field is a digit it has to be a tuple.
             && field.ident.as_str().as_bytes().first().is_some_and(u8::is_ascii_digit)
             // Type aliases can't be used as functions.
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 66931a7f98c..f4e41dc826b 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty;
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 644365c9fe5..623b6b4fcc1 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -3,8 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::impl_lint_pass;
 use rustc_span::{BytePos, Pos, Span};
 
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index 4f22931a4de..b38e362410e 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
             && let AttrKind::Normal(ref normal) = attr.kind
             && let Some(doc) = attr.doc_str()
             && doc.as_str().len() as u64 > self.max_file_size
-            && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
+            && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
             && !attr.span.contains(meta.span)
             // Since the `include_str` is already expanded at this point, we can only take the
             // whole attribute snippet and then modify for our suggestion.
diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
index e17d6213679..fb46bdcab6e 100644
--- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::{get_parent_expr, is_from_proc_macro};
 use hir::def_id::DefId;
 use rustc_errors::Applicability;
@@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
         // Integer modules are "TBD" deprecated, and the contents are too,
         // so lint on the `use` statement directly.
         if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind
-            && self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS)
+            && self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
             && !in_external_macro(cx.sess(), item.span)
             && let Some(def_id) = path.res[0].opt_def_id()
         {
@@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
             return;
         };
 
-        if self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS)
+        if self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
             && !in_external_macro(cx.sess(), expr.span)
             && !is_from_proc_macro(cx, expr)
         {
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index c9064df25ac..e80cca6e7db 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -363,7 +363,6 @@ mod uninhabited_references;
 mod uninit_vec;
 mod unit_return_expecting_ord;
 mod unit_types;
-mod unnamed_address;
 mod unnecessary_box_returns;
 mod unnecessary_literal_bound;
 mod unnecessary_map_on_constructor;
@@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
     store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
     store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
-    store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
     store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 6ff1a1e5ec7..35b14776e59 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
 use itertools::Itertools;
+use rustc_ast::visit::{try_visit, walk_list};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::Applicability;
 use rustc_hir::FnRetTy::Return;
@@ -11,8 +12,9 @@ use rustc_hir::intravisit::{
 };
 use rustc_hir::{
     BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
-    Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
-    PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, WherePredicateKind, lang_items,
+    HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
+    PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate,
+    WherePredicateKind, lang_items,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
@@ -483,6 +485,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
 struct Usage {
     lifetime: Lifetime,
     in_where_predicate: bool,
+    in_bounded_ty: bool,
     in_generics_arg: bool,
 }
 
@@ -490,11 +493,15 @@ struct LifetimeChecker<'cx, 'tcx, F> {
     cx: &'cx LateContext<'tcx>,
     map: FxIndexMap<LocalDefId, Vec<Usage>>,
     where_predicate_depth: usize,
+    bounded_ty_depth: usize,
     generic_args_depth: usize,
     phantom: std::marker::PhantomData<F>,
 }
 
-impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
+impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F>
+where
+    F: NestedFilter<'tcx>,
+{
     fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> {
         let map = generics
             .params
@@ -510,10 +517,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
             cx,
             map,
             where_predicate_depth: 0,
+            bounded_ty_depth: 0,
             generic_args_depth: 0,
             phantom: std::marker::PhantomData,
         }
     }
+
+    // `visit_where_bound_predicate` is based on:
+    // https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939
+    fn visit_where_bound_predicate(
+        &mut self,
+        hir_id: HirId,
+        bounded_ty: &'tcx Ty<'tcx>,
+        bounds: &'tcx [GenericBound<'tcx>],
+        bound_generic_params: &'tcx [GenericParam<'tcx>],
+    ) {
+        try_visit!(self.visit_id(hir_id));
+
+        self.bounded_ty_depth += 1;
+        try_visit!(self.visit_ty(bounded_ty));
+        self.bounded_ty_depth -= 1;
+
+        walk_list!(self, visit_param_bound, bounds);
+        walk_list!(self, visit_generic_param, bound_generic_params);
+    }
 }
 
 impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
@@ -531,6 +558,7 @@ where
             usages.push(Usage {
                 lifetime: *lifetime,
                 in_where_predicate: self.where_predicate_depth != 0,
+                in_bounded_ty: self.bounded_ty_depth != 0,
                 in_generics_arg: self.generic_args_depth != 0,
             });
         }
@@ -538,7 +566,17 @@ where
 
     fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
         self.where_predicate_depth += 1;
-        walk_where_predicate(self, predicate);
+        if let &WherePredicateKind::BoundPredicate(WhereBoundPredicate {
+            bounded_ty,
+            bounds,
+            bound_generic_params,
+            origin: _,
+        }) = predicate.kind
+        {
+            self.visit_where_bound_predicate(predicate.hir_id, bounded_ty, bounds, bound_generic_params);
+        } else {
+            walk_where_predicate(self, predicate);
+        }
         self.where_predicate_depth -= 1;
     }
 
@@ -562,7 +600,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
     for (def_id, usages) in checker.map {
         if usages
             .iter()
-            .all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
+            .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
         {
             span_lint(
                 cx,
@@ -589,7 +627,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
     for (&def_id, usages) in &checker.map {
         if usages
             .iter()
-            .all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
+            .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
         {
             span_lint(
                 cx,
@@ -605,8 +643,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
 
 // An `impl` lifetime is elidable if it satisfies the following conditions:
 // - It is used exactly once.
-// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
-//   different from `GenericParam`s.)
+// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that
+//   `GenericArgs` are different from `GenericParam`s.)
 fn report_elidable_impl_lifetimes<'tcx>(
     cx: &LateContext<'tcx>,
     impl_: &'tcx Impl<'_>,
@@ -623,6 +661,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
                 }
                 | Usage {
                     lifetime,
+                    in_bounded_ty: false,
                     in_generics_arg: false,
                     ..
                 },
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index d999e1a0585..06cf901bfb2 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -1,6 +1,6 @@
 use super::EXPLICIT_ITER_LOOP;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
@@ -29,7 +29,7 @@ pub(super) fn check(
             if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
                 return;
             }
-        } else if count.try_to_target_usize(cx.tcx).map_or(true, |x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) {
+        } else if count.try_to_target_usize(cx.tcx).is_none_or(|x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) {
             return;
         }
     }
@@ -181,7 +181,8 @@ fn is_ref_iterable<'tcx>(
             // Attempt to borrow
             let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl);
             if implements_trait(cx, self_ty, trait_id, &[])
-                && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
+                && let Some(ty) =
+                    make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
                 && ty == res_ty
             {
                 return Some((AdjustKind::borrow(mutbl), self_ty));
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 17215621d2a..f3ca4a4a571 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -23,8 +23,8 @@ mod while_let_loop;
 mod while_let_on_iterator;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::higher;
+use clippy_utils::msrvs::Msrv;
 use rustc_ast::Label;
 use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
 use rustc_lint::{LateContext, LateLintPass};
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 1c55e3e22e8..ed9879de13b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -5,7 +5,7 @@ use clippy_utils::higher::ForLoop;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
-use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
+use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind, StructTailExpr};
 use rustc_lint::LateContext;
 use rustc_span::{Span, sym};
 use std::iter::once;
@@ -164,7 +164,7 @@ fn never_loop_expr<'tcx>(
         },
         ExprKind::Struct(_, fields, base) => {
             let fields = never_loop_expr_all(cx, fields.iter().map(|f| f.expr), local_labels, main_loop_id);
-            if let Some(base) = base {
+            if let StructTailExpr::Base(base) = base {
                 combine_seq(fields, || never_loop_expr(cx, base, local_labels, main_loop_id))
             } else {
                 fields
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index 35dc8e9aa4e..12719c4f94b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
 use clippy_utils::visitors::contains_break_or_continue;
 use rustc_ast::Mutability;
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
 use rustc_lint::LateContext;
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
         if !prefix.is_empty()
             && (
                 // Precedence of internal expression is less than or equal to precedence of `&expr`.
-                arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression)
+                arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
             )
         {
             arg_snip = format!("({arg_snip})").into();
diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs
index fd71167f814..c31656f8a05 100644
--- a/src/tools/clippy/clippy_lints/src/manual_bits.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::packed::Pu128;
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index 016ec7320a6..484a7ba256b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -1,8 +1,8 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::higher::If;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::is_const_evaluatable;
diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
index 4c171e6d890..bbb89bee835 100644
--- a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use rustc_ast::{BinOpKind, LitKind};
@@ -35,7 +35,7 @@ declare_clippy_lint! {
     /// let y: i32 = 4;
     /// let div = x.div_ceil(y);
     /// ```
-    #[clippy::version = "1.81.0"]
+    #[clippy::version = "1.83.0"]
     pub MANUAL_DIV_CEIL,
     complexity,
     "manually reimplementing `div_ceil`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
index a269ea11397..b12f575e81a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
@@ -1,7 +1,7 @@
-use clippy_config::msrvs::Msrv;
-use clippy_config::{Conf, msrvs};
+use clippy_config::Conf;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_from_proc_macro, path_to_local};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
index 7a9c9963742..7e092d11f1b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::visitors::{is_local_used, local_used_once};
 use clippy_utils::{is_trait_method, path_to_local_id};
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index dec8c5d85de..3f01f3cf30a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators};
 use rustc_ast::LitKind::{Byte, Char};
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
index a11d3e4624c..4fee3bf7aa9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
@@ -27,7 +27,7 @@ declare_clippy_lint! {
     /// let a: u32 = 4;
     /// let result = a.is_power_of_two();
     /// ```
-    #[clippy::version = "1.82.0"]
+    #[clippy::version = "1.83.0"]
     pub MANUAL_IS_POWER_OF_TWO,
     pedantic,
     "manually reimplementing `is_power_of_two`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 17185df5d76..a70955a7c78 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -1,11 +1,10 @@
 use crate::question_mark::{QUESTION_MARK, QuestionMark};
-use clippy_config::msrvs;
 use clippy_config::types::MatchLintBehaviour;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_lint_allowed, is_never_expr, pat_and_expr_can_be_question_mark, peel_blocks};
+use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
index 85e99a92cf5..b7563a2508d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::{is_trait_method, peel_hir_expr_refs};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
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 25868ccae40..00800231fe4 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::is_doc_hidden;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_indent;
 use itertools::Itertools;
 use rustc_ast::attr;
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 86293169ea2..5e58054a986 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, FullInt};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::{is_in_const_context, path_to_local};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index a60163be770..708980ac503 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 3f401eff6bd..79de41db343 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::{eq_expr_value, higher};
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index 50e6dfc6298..99a7b8c74be 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
+use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{
@@ -72,14 +72,13 @@ fn check_arm<'tcx>(
             (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
         }
         // the binding must not be used in the if guard
-        && outer_guard.map_or(
-            true,
+        && outer_guard.is_none_or(
             |e| !is_local_used(cx, e, binding_id)
         )
         // ...or anywhere in the inner expression
         && match inner {
             IfLetOrMatch::IfLet(_, _, body, els, _) => {
-                !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id))
+                !is_local_used(cx, body, binding_id) && els.is_none_or(|e| !is_local_used(cx, e, binding_id))
             },
             IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)),
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
index 9c6df4d8ac0..bac5cf88cfb 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
@@ -7,7 +7,7 @@ use clippy_utils::{
     CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
     path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
 };
-use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::def::Res;
@@ -117,7 +117,7 @@ where
     // it's being passed by value.
     let scrutinee = peel_hir_expr_refs(scrutinee).0;
     let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
-    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS {
+    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
         format!("({scrutinee_str})")
     } else {
         scrutinee_str.into()
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 28adcc2f227..64969271764 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,7 +25,7 @@ mod try_err;
 mod wild_in_or_pats;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::walk_span_to_context;
 use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg};
 use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index 9e54475033c..dfc0513add9 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
+use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used};
 use clippy_utils::{is_in_const_context, path_to_local};
@@ -243,11 +243,6 @@ fn emit_redundant_guards<'tcx>(
 }
 
 /// Checks if the given `Expr` can also be represented as a `Pat`.
-///
-/// All literals generally also work as patterns, however float literals are special.
-/// They are currently (as of 2023/08/08) still allowed in patterns, but that will become
-/// an error in the future, and rustc already actively warns against this (see rust#41620),
-/// so we don't consider those as usable within patterns for linting purposes.
 fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     for_each_expr_without_closures(expr, |expr| {
         if match expr.kind {
@@ -267,7 +262,7 @@ fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
             | ExprKind::Tup(..)
             | ExprKind::Struct(..)
             | ExprKind::Unary(UnOp::Neg, _) => true,
-            ExprKind::Lit(lit) if !matches!(lit.node, LitKind::Float(..)) => true,
+            ExprKind::Lit(lit) if !matches!(lit.node, LitKind::CStr(..)) => true,
             _ => false,
         } {
             return ControlFlow::Continue(());
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 146748734cf..5597cd85abc 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_non_aggregate_primitive_type;
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index c9604c7b2e2..1ee27d90d05 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -30,7 +30,7 @@ pub(super) fn check(
         .type_dependent_def_id(expr.hir_id)
         .and_then(|id| cx.tcx.trait_of_item(id))
         .zip(cx.tcx.lang_items().clone_trait())
-        .map_or(true, |(x, y)| x != y)
+        .is_none_or(|(x, y)| x != y)
     {
         return;
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
index fa04f74eec1..2a0a9d3710d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::ty::{get_iterator_item_ty, is_copy};
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
index 3b1adb16b80..44b55570eea 100644
--- a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
@@ -1,6 +1,6 @@
 use super::ERR_EXPECT;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
index f94fe221833..3f89e593148 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::is_trait_method;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
index 40b48ccca5d..d8bb9e377a0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -1,7 +1,7 @@
 use super::IS_DIGIT_ASCII_RADIX;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, FullInt};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 390dd24b505..299f6d10112 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -1,6 +1,6 @@
 use super::ITER_KV_MAP;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::pat_is_wild;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
index 22f4748de70..7d5ebdedd0c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use rustc_ast::{LitKind, StrStyle};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
index 7aa13d8d5b6..20e4d233525 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::get_field_by_name;
 use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures};
@@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
                                 _ => {},
                             }
                         }
-                        requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
+                        requires_copy |= !cx.type_is_copy_modulo_regions(ty);
                         break;
                     }
                 },
@@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
         }
 
         if can_lint
-            && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()))
+            && (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty))
             // This case could be handled, but a fair bit of care would need to be taken.
             && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env()))
         {
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
index c377abd6237..90e502f244f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{Msrv, OPTION_RESULT_IS_VARIANT_AND};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
     }
 
     // 4. msrv doesn't meet `OPTION_RESULT_IS_VARIANT_AND`
-    if !msrv.meets(OPTION_RESULT_IS_VARIANT_AND) {
+    if !msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
index 31449d41770..4a48d4b547c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_from_proc_macro, is_trait_method};
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index d5594b21db5..1252f7ccd35 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function};
 use clippy_utils::{is_diag_trait_item, peel_blocks};
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
index 3226fa9cd3f..428da0cf107 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::mutated_variables;
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
index fc656fd78ba..80703618a11 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
@@ -1,6 +1,6 @@
 use crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{eager_or_lazy, higher, usage};
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 795e041ffd9..7d1d5d69c99 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -137,10 +137,10 @@ mod wrong_self_convention;
 mod zst_offset;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::macros::FormatArgsStorage;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
 use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty};
 pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES;
@@ -4107,24 +4107,32 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome,
     /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`.
+    /// Also, calls such as `opt.map_or(true, |val| val == 5)` can be reduced to
+    /// `opt.is_none_or(|val| val == 5)`.
     /// This lint offers readability and conciseness improvements.
     ///
     /// ### Example
     /// ```no_run
-    /// pub fn a(x: Option<i32>) -> bool {
-    ///     x.map_or(false, |n| n == 5)
+    /// pub fn a(x: Option<i32>) -> (bool, bool) {
+    ///     (
+    ///         x.map_or(false, |n| n == 5),
+    ///         x.map_or(true, |n| n > 5),
+    ///     )
     /// }
     /// ```
     /// Use instead:
     /// ```no_run
-    /// pub fn a(x: Option<i32>) -> bool {
-    ///     x == Some(5)
+    /// pub fn a(x: Option<i32>) -> (bool, bool) {
+    ///     (
+    ///         x == Some(5),
+    ///         x.is_none_or(|n| n > 5),
+    ///     )
     /// }
     /// ```
-    #[clippy::version = "1.75.0"]
+    #[clippy::version = "1.84.0"]
     pub UNNECESSARY_MAP_OR,
     style,
-    "reduce unnecessary pattern matching for constructs that implement `PartialEq`"
+    "reduce unnecessary calls to `.map_or(bool, …)`"
 }
 
 declare_clippy_lint! {
@@ -4531,7 +4539,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                         && method_config.output_type.matches(&sig.decl.output)
                         // in case there is no first arg, since we already have checked the number of arguments
                         // it's should be always true
-                        && first_arg_ty_opt.map_or(true, |first_arg_ty| method_config
+                        && first_arg_ty_opt.is_none_or(|first_arg_ty| method_config
                             .self_kind.matches(cx, self_ty, first_arg_ty)
                             )
                         && fn_header_equals(method_config.fn_header, sig.header)
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index c00b9b368c4..ea4984f83ad 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -203,7 +203,8 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
 fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool {
     if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
         && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
-        && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty])
+        && let Some(iter_item_ty) =
+            make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty])
         && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty])
         && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
             cx.typing_env(),
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 998bdee0157..8d97d1c72a6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{path_to_local_id, peel_blocks};
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 528e2204cf8..7c4dc4ffb20 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
 use rustc_data_structures::fx::FxHashSet;
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
index cfb823dbf5d..febd7fd5cf2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
@@ -1,6 +1,6 @@
 use super::PATH_ENDS_WITH_EXT;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::{LitKind, StrStyle};
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 1cee28e1986..c91be33b1cd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -1,6 +1,6 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::usage::local_used_after_expr;
 use clippy_utils::visitors::{Descend, for_each_expr};
diff --git a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs
index cc0d432b799..cb719b34b1f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
 use itertools::Itertools;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index bab439015c5..3de51bc661e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
     if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind {
         let body = cx.tcx.hir().body(body);
         let arg_id = body.params[0].pat.hir_id;
-        let mutates_arg = mutated_variables(body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id));
+        let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id));
         let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value);
 
         let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value);
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 adc27cd437f..1199d289761 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
@@ -1,8 +1,8 @@
 use std::borrow::Cow;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::sugg::{Sugg, make_binop};
 use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
@@ -60,7 +60,7 @@ pub(super) fn check<'a>(
         Some(_) | None => return,
     };
 
-    let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind
+    let (sugg, method, applicability) = if let ExprKind::Closure(map_closure) = map.kind
             && let closure_body = cx.tcx.hir().body(map_closure.body)
             && let closure_body_value = closure_body.value.peel_blocks()
             && let ExprKind::Binary(op, l, r) = closure_body_value.kind
@@ -100,7 +100,7 @@ pub(super) fn check<'a>(
             .maybe_par()
             .into_string();
 
-        (binop, "a standard comparison")
+        (binop, "a standard comparison", Applicability::MaybeIncorrect)
     } else if !def_bool
         && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND)
         && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite())
@@ -110,6 +110,18 @@ pub(super) fn check<'a>(
         (
             format!("{recv_callsite}.{suggested_name}({span_callsite})",),
             suggested_name,
+            Applicability::MachineApplicable,
+        )
+    } else if def_bool
+        && matches!(variant, Variant::Some)
+        && msrv.meets(msrvs::IS_NONE_OR)
+        && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite())
+        && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite())
+    {
+        (
+            format!("{recv_callsite}.is_none_or({span_callsite})"),
+            "is_none_or",
+            Applicability::MachineApplicable,
         )
     } else {
         return;
@@ -123,9 +135,9 @@ pub(super) fn check<'a>(
         cx,
         UNNECESSARY_MAP_OR,
         expr.span,
-        "this `map_or` is redundant",
+        "this `map_or` can be simplified",
         format!("use {method} instead"),
         sugg,
-        Applicability::MaybeIncorrect,
+        applicability,
     );
 }
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 84ea3554a35..d19064fd57e 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
@@ -1,7 +1,7 @@
 use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{SpanRangeExt, snippet};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 408dbef9cb1..b856c929cf6 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -114,7 +114,7 @@ declare_clippy_lint! {
     ///     let _ = FooStruct{};
     /// }
     /// ```
-    #[clippy::version = "pre 1.29.0"]
+    #[clippy::version = "1.83.0"]
     pub USED_UNDERSCORE_ITEMS,
     pedantic,
     "using a item which is prefixed with an underscore"
@@ -351,7 +351,7 @@ fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 /// `unused_variables`'s idea
 /// of what it means for an expression to be "used".
 fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind {
+    get_parent_expr(cx, expr).is_none_or(|parent| match parent.kind {
         ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr),
         _ => is_used(cx, parent),
     })
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index eea0459e026..121c4326d64 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
index c2f524a6353..9a44a3c980c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::source::snippet;
 use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks};
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index 9ebef531bc5..f69913ddbfd 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir, expr_local, local_assignments, used_exactly_once};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs};
@@ -362,7 +362,7 @@ fn referent_used_exactly_once<'tcx>(
         let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
         if possible_borrowers
             .last()
-            .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id)
+            .is_none_or(|&(local_def_id, _)| local_def_id != body_owner_local_def_id)
         {
             possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
         }
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 b65ec8c3c48..6f3f371a68d 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
@@ -182,14 +182,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 && !is_copy(cx, ty)
                 && ty.is_sized(cx.tcx, cx.typing_env())
                 && !allowed_traits.iter().any(|&t| {
-                    implements_trait_with_env_from_iter(
-                        cx.tcx,
-                        cx.typing_env(),
-                        ty, 
-                        t,
-                        None,
-                        [None::<ty::GenericArg<'tcx>>]
-                    )
+                    implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, t, None, [None::<
+                        ty::GenericArg<'tcx>,
+                    >])
                 })
                 && !implements_borrow_trait
                 && !all_borrowable_trait
@@ -205,6 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                 cx.param_env,
                                 ty,
                                 traits::ObligationCause::dummy_with_span(span),
+                                rustc_hir::Safety::Safe,
                             )
                             .is_ok()
                             {
diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs
index 6a2893cefbd..0cba72bd2c6 100644
--- a/src/tools/clippy/clippy_lints/src/needless_update.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_update.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
@@ -51,7 +51,7 @@ declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]);
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Struct(_, fields, Some(base)) = expr.kind {
+        if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind {
             let ty = cx.typeck_results().expr_ty(expr);
             if let ty::Adt(def, _) = ty.kind() {
                 if fields.len() == def.non_enum_variant().fields.len()
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index a0ba2aaf552..429afff9b66 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::has_enclosing_paren;
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
     {
         let mut applicability = Applicability::MachineApplicable;
         let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
-        let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) {
+        let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
             format!("-({snip})")
         } else {
             format!("-{snip}")
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 74536028b5d..9e44bb02c56 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{
     BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind, Stmt, StmtKind,
-    UnsafeSource, is_range_literal,
+    UnsafeSource, StructTailExpr, is_range_literal,
 };
 use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -238,7 +238,10 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         ExprKind::Struct(_, fields, ref base) => {
             !has_drop(cx, cx.typeck_results().expr_ty(expr))
                 && fields.iter().all(|field| has_no_effect(cx, field.expr))
-                && base.as_ref().map_or(true, |base| has_no_effect(cx, base))
+                && match &base {
+                    StructTailExpr::None | StructTailExpr::DefaultFields(_) => true,
+                    StructTailExpr::Base(base) => has_no_effect(cx, base),
+                }
         },
         ExprKind::Call(callee, args) => {
             if let ExprKind::Path(ref qpath) = callee.kind {
@@ -342,6 +345,10 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
             if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
                 None
             } else {
+                let base = match base {
+                    StructTailExpr::Base(base) => Some(base),
+                    StructTailExpr::None | StructTailExpr::DefaultFields(_) => None,
+                };
                 Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 5416e00fe0c..ebd301d5156 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -11,7 +11,7 @@ use rustc_hir::{
     BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass, Lint};
-use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
+use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId, ReportedErrorInfo};
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
@@ -278,7 +278,12 @@ impl<'tcx> NonCopyConst<'tcx> {
     fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
         let args = cx.typeck_results().node_args(hir_id);
 
-        let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
+        let result = Self::const_eval_resolve(
+            cx.tcx,
+            cx.typing_env(),
+            ty::UnevaluatedConst::new(def_id, args),
+            DUMMY_SP,
+        );
         Self::is_value_unfrozen_raw(cx, result, ty)
     }
 
@@ -297,7 +302,10 @@ impl<'tcx> NonCopyConst<'tcx> {
                 tcx.const_eval_global_id_for_typeck(typing_env, cid, span)
             },
             Ok(None) => Err(ErrorHandled::TooGeneric(span)),
-            Err(err) => Err(ErrorHandled::Reported(err.into(), span)),
+            Err(err) => Err(ErrorHandled::Reported(
+                ReportedErrorInfo::non_const_eval_error(err),
+                span,
+            )),
         }
     }
 }
@@ -335,7 +343,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
                 // i.e. having an enum doesn't necessary mean a type has a frozen variant.
                 // And, implementing it isn't a trivial task; it'll probably end up
                 // re-implementing the trait predicate evaluation specific to `Freeze`.
-                && body_id_opt.map_or(true, |body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized))
+                && body_id_opt.is_none_or(|body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized))
             {
                 lint(cx, Source::Assoc { item: trait_item.span });
             }
diff --git a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
index aefb665b52e..f6ce1d1d586 100644
--- a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
@@ -39,7 +39,7 @@ declare_clippy_lint! {
     ///     let r2 = x % NonZeroU64::from(y);
     /// }
     /// ```
-    #[clippy::version = "1.81.0"]
+    #[clippy::version = "1.83.0"]
     pub NON_ZERO_SUGGESTIONS,
     restriction,
     "suggests using `NonZero#` from `u#` or `i#` for more efficient and type-safe conversions"
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 13b3d240700..6de203e068b 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -200,7 +200,7 @@ impl Params {
                 if self
                     .get_by_fn(param.fn_id, usage.idx)
                     // If the parameter can't be found, then it's used for more than just recursion.
-                    .map_or(true, |p| self.try_disable_lint_for_param(p, eval_stack))
+                    .is_none_or(|p| self.try_disable_lint_for_param(p, eval_stack))
                 {
                     param.apply_lint.set(false);
                     eval_stack.pop();
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 0dcaec1c9a7..1315c3dfc12 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
             if let Some((_, lang_item)) = binop_traits(op.node)
                 && let Some(trait_id) = cx.tcx.lang_items().get(lang_item)
                 && let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id
-                && trait_ref_of_method(cx, parent_fn).map_or(true, |t| t.path.res.def_id() != trait_id)
+                && trait_ref_of_method(cx, parent_fn).is_none_or(|t| t.path.res.def_id() != trait_id)
                 && implements_trait(cx, ty, trait_id, &[rty.into()])
             {
                 // Primitive types execute assign-ops right-to-left. Every other type is left-to-right.
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 4414056a467..e87cfd103c3 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -1,5 +1,6 @@
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_from_proc_macro;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_span::Span;
@@ -35,9 +36,9 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind {
     }
 }
 
-fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp_value: u128, span: Span) {
+fn check_compare<'a>(cx: &LateContext<'a>, bit_op: &Expr<'a>, cmp_op: BinOpKind, cmp_value: u128, span: Span) {
     if let ExprKind::Binary(op, left, right) = &bit_op.kind {
-        if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr {
+        if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr || is_from_proc_macro(cx, bit_op) {
             return;
         }
         if let Some(mask) = fetch_int_literal(cx, right).or_else(|| fetch_int_literal(cx, left)) {
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index ecc095f3859..dec4c18a309 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -541,9 +541,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
             .collect();
         if let Some(args) = args
             && !args.is_empty()
-            && body.map_or(true, |body| {
-                sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value)
-            })
+            && body.is_none_or(|body| sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value))
         {
             span_lint_and_then(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index f69cb9be4ca..77abe7151f0 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -1,9 +1,9 @@
 use crate::manual_let_else::MANUAL_LET_ELSE;
 use crate::question_mark_used::QUESTION_MARK_USED;
 use clippy_config::Conf;
-use clippy_config::msrvs::Msrv;
 use clippy_config::types::MatchLintBehaviour;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{
@@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
     {
         let mut applicability = Applicability::MachineApplicable;
         let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
-        let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
+        let by_ref = !cx.type_is_copy_modulo_regions(caller_ty)
             && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
         let sugg = if let Some(else_inner) = r#else {
             if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 21cd3367262..1b0c0a4956f 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local};
diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
index 313e4083256..3ade6bcee84 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -88,7 +88,7 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op
         cx.typeck_results()
             .closure_min_captures
             .get(def_id)
-            .map_or(true, |m| {
+            .is_none_or(|m| {
                 m.values().all(|places| {
                     places
                         .iter()
diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
index d0dbff081f9..347540e7344 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 79baa914b03..8e3472b1b5a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
 use rustc_lint::{LateContext, LateLintPass, Lint};
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
             let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
             let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
             let parent_expr = get_parent_expr(cx, expr);
-            let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX);
+            let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
 
             if expr_ty == indexed_ty {
                 if expr_ref_count > indexed_ref_count {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
index b27bb2e78af..06c85433806 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
 use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
index abe13a97c0d..0176077c70e 100644
--- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -93,7 +93,7 @@ impl SingleCallFn {
                 .tcx
                 .hir()
                 .maybe_body_owned_by(fn_def_id)
-                .map_or(true, |body| is_in_test_function(cx.tcx, body.value.hir_id))
+                .is_none_or(|body| is_in_test_function(cx.tcx, body.value.hir_id))
             || match cx.tcx.hir_node(fn_hir_id) {
                 Node::Item(item) => is_from_proc_macro(cx, item),
                 Node::ImplItem(item) => is_from_proc_macro(cx, item),
diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
index 44e585953bf..bb11daecc07 100644
--- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use rustc_ast::{LitIntType, LitKind, UintTy};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, LangItem, QPath};
+use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use std::fmt::{self, Display, Formatter};
@@ -86,7 +86,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
             return;
         };
 
-        let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else {
+        let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], StructTailExpr::None) = inner_expr.kind else {
             return;
         };
 
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 8dd99858793..2941b9c3960 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
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
+use clippy_utils::msrvs::Msrv;
 use rustc_attr::{StabilityLevel, StableSince};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index ba2ddac2ec3..0d85b1b858a 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -1,10 +1,10 @@
 use std::ops::ControlFlow;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::macros::matching_root_macro_call;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::path_to_local_id;
 use clippy_utils::source::{snippet, str_literal_to_char_literal};
 use clippy_utils::visitors::{Descend, for_each_expr};
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 50a1577b288..a1d92c3ac71 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -56,9 +56,10 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
 fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
     if let ItemKind::Struct(data, _) = &item.kind
         && let Some(last_field) = data.fields().last()
-        && let field_ty = cx
-            .tcx
-            .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity())
+        && let field_ty = cx.tcx.normalize_erasing_regions(
+            cx.typing_env(),
+            cx.tcx.type_of(last_field.def_id).instantiate_identity(),
+        )
         && let ty::Array(_, array_len) = *field_ty.kind()
         && let Some(0) = array_len.try_to_target_usize(cx.tcx)
     {
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 6f3c6682305..99844beb8f0 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
 use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro};
 use core::hash::{Hash, Hasher};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 25fec9f688c..1cb0f837227 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -20,8 +20,8 @@ mod utils;
 mod wrong_transmute;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::is_in_const_context;
+use clippy_utils::msrvs::Msrv;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index 3507eb9a124..f0b8abf9af6 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_FLOAT_TO_INT;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg;
 use rustc_ast as ast;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index c5c7ed6d398..e5b9aea6423 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_INT_TO_FLOAT;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index a94cd27c7fd..6d828bad9b3 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_NUM_TO_BYTES;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index bf6700b1b6b..c4a2e20fa9d 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_PTR_TO_PTR;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index eaf927c0005..ef18633d945 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_PTR_TO_REF;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index cad15b1e982..0d5cf45a5e6 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -1,7 +1,7 @@
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
-use rustc_ast::util::parser::AssocOp;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Node};
 use rustc_hir_typeck::cast::check_cast;
@@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
     };
 
     if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
-        && parent.precedence() > AssocOp::As.precedence() as i8
+        && parent.precedence() > ExprPrecedence::Cast
     {
         sugg = format!("({sugg})");
     }
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
index 07d0f59b91c..99a55f9fc35 100644
--- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{is_from_proc_macro, path_to_local};
 use itertools::Itertools;
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 0bba611116b..b79e59f857b 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -337,7 +337,7 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
         .src
         .as_deref()
         .and_then(|src| src.get(file_pos.pos.to_usize()..))
-        .map_or(true, |src| !src.starts_with("unsafe"))
+        .is_none_or(|src| !src.starts_with("unsafe"))
 }
 
 // Checks if any parent {expression, statement, block, local, const, static}
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 6eef582b4b2..0702f6d1e74 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
@@ -145,7 +145,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -
     }
     while let Some(id) = locals_to_check.pop() {
         if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) {
-            if !l.ty.map_or(true, |ty| matches!(ty.kind, TyKind::Infer)) {
+            if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer)) {
                 return false;
             }
             if let Some(e) = l.init {
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
deleted file mode 100644
index cd2dacc9f09..00000000000
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
-use rustc_session::declare_lint_pass;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparisons with an address of a function item.
-    ///
-    /// ### Why is this bad?
-    /// Function item address is not guaranteed to be unique and could vary
-    /// between different code generation units. Furthermore different function items could have
-    /// the same address after being merged together.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// type F = fn();
-    /// fn a() {}
-    /// let f: F = a;
-    /// if f == a {
-    ///     // ...
-    /// }
-    /// ```
-    #[clippy::version = "1.44.0"]
-    pub FN_ADDRESS_COMPARISONS,
-    correctness,
-    "comparison with an address of a function item"
-}
-
-declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
-
-impl LateLintPass<'_> for UnnamedAddress {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        fn is_comparison(binop: BinOpKind) -> bool {
-            matches!(
-                binop,
-                BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
-            )
-        }
-
-        fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-            matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
-        }
-
-        if let ExprKind::Binary(binop, left, right) = expr.kind
-            && is_comparison(binop.node)
-            && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
-            && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
-            && (is_fn_def(cx, left) || is_fn_def(cx, right))
-        {
-            span_lint(
-                cx,
-                FN_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing with a non-unique address of a function item",
-            );
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
index afdd3505cdd..0a90d31db7e 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{get_parent_expr, path_to_local};
-use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, UnOp};
+use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, UnOp, StructTailExpr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
@@ -59,15 +59,15 @@ impl LateLintPass<'_> for UnnecessaryStruct {
         let field_path = same_path_in_all_fields(cx, expr, fields);
 
         let sugg = match (field_path, base) {
-            (Some(&path), None) => {
+            (Some(&path), StructTailExpr::None | StructTailExpr::DefaultFields(_)) => {
                 // all fields match, no base given
                 path.span
             },
-            (Some(path), Some(base)) if base_is_suitable(cx, expr, base) && path_matches_base(path, base) => {
+            (Some(path), StructTailExpr::Base(base)) if base_is_suitable(cx, expr, base) && path_matches_base(path, base) => {
                 // all fields match, has base: ensure that the path of the base matches
                 base.span
             },
-            (None, Some(base)) if fields.is_empty() && base_is_suitable(cx, expr, base) => {
+            (None, StructTailExpr::Base(base)) if fields.is_empty() && base_is_suitable(cx, expr, base) => {
                 // just the base, no explicit fields
                 base.span
             },
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index c7c837de505..50a97579df7 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -1,9 +1,9 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::over;
 use rustc_ast::PatKind::*;
 use rustc_ast::mut_visit::*;
@@ -234,7 +234,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
         // In the case of only two patterns, replacement adds net characters.
         | Ref(_, Mutability::Not)
         // Dealt with elsewhere.
-        | Or(_) | Paren(_) | Deref(_) => false,
+        | Or(_) | Paren(_) | Deref(_) | Guard(..) => false,
         // Transform `box x | ... | box y` into `box (x | y)`.
         //
         // The cases below until `Slice(...)` deal with *singleton* products.
diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
index 9fd6ebccd02..17ee5fc20ca 100644
--- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 8de062a8fc1..c3843279ba2 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -93,7 +93,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive
         while let Some(c) = s.next() {
             r.push(
                 if replace(&mut prev_upper, c.is_ascii_uppercase())
-                    && s.clone().next().map_or(true, |c| c.is_ascii_uppercase())
+                    && s.clone().next().is_none_or(|c| c.is_ascii_uppercase())
                 {
                     c.to_ascii_lowercase()
                 } else {
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index f5cf4a586fd..05c5be03002 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::ty::same_type_and_consts;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args
             && parameters
                 .as_ref()
-                .map_or(true, |params| params.parenthesized == GenericArgsParentheses::No)
+                .is_none_or(|params| params.parenthesized == GenericArgsParentheses::No)
             && !item.span.from_expansion()
             && !is_from_proc_macro(cx, item)
         // expensive, should be last check
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 51001d374b4..311ed427cb9 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
-    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
+    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, StructTailExpr,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -598,7 +598,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
             },
             ExprKind::Struct(qpath, fields, base) => {
                 bind!(self, qpath, fields);
-                opt_bind!(self, base);
+                let base = OptionPat::new(match base {
+                    StructTailExpr::Base(base) => Some(self.bind("base", base)),
+                    StructTailExpr::None | StructTailExpr::DefaultFields(_) => None,
+                });
                 kind!("Struct({qpath}, {fields}, {base})");
                 self.qpath(qpath);
                 self.slice(fields, |field| {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 96397375d5e..a5fad68eea1 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -5,8 +5,8 @@ use rustc_hir as hir;
 use rustc_hir::Item;
 use rustc_hir::def::DefKind;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::FloatTy;
 use rustc_middle::ty::fast_reject::SimplifiedType;
+use rustc_middle::ty::{self, FloatTy};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
 
@@ -32,9 +32,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
         let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
         if mod_name.as_str() == "paths"
             && let hir::ItemKind::Const(.., body_id) = item.kind
-            && let Some(Constant::Vec(path)) =
-                ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(item.owner_id), cx.tcx.typeck(item.owner_id))
-                    .eval_simple(cx.tcx.hir().body(body_id).value)
+            && let Some(Constant::Vec(path)) = ConstEvalCtxt::with_env(
+                cx.tcx,
+                ty::TypingEnv::post_analysis(cx.tcx, item.owner_id),
+                cx.tcx.typeck(item.owner_id),
+            )
+            .eval_simple(cx.tcx.hir().body(body_id).value)
             && let Some(path) = path
                 .iter()
                 .map(|x| {
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 9bcff9d7bce..ef1c46154d2 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -2,9 +2,9 @@ use std::collections::BTreeMap;
 use std::ops::ControlFlow;
 
 use clippy_config::Conf;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
 use clippy_utils::visitors::for_each_local_use_after_expr;
diff --git a/src/tools/clippy/clippy_lints/src/zombie_processes.rs b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
index 8d9241cc7d9..4a13c10166f 100644
--- a/src/tools/clippy/clippy_lints/src/zombie_processes.rs
+++ b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
@@ -35,7 +35,7 @@ declare_clippy_lint! {
     /// let mut child = Command::new("ls").spawn().expect("failed to execute child");
     /// child.wait().expect("failed to wait on child");
     /// ```
-    #[clippy::version = "1.74.0"]
+    #[clippy::version = "1.83.0"]
     pub ZOMBIE_PROCESSES,
     suspicious,
     "not waiting on a spawned child process"
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index d8d5733da1c..945827c98c1 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,15 +1,22 @@
 [package]
 name = "clippy_utils"
-version = "0.1.84"
+# begin autogenerated version
+version = "0.1.85"
+# end autogenerated version
 edition = "2021"
-publish = false
+description = "Helpful tools for writing lints, provided as they are used in Clippy"
+repository = "https://github.com/rust-lang/rust-clippy"
+readme = "README.md"
+license = "MIT OR Apache-2.0"
+keywords = ["clippy", "lint", "utils"]
+categories = ["development-tools"]
 
 [dependencies]
-clippy_config = { path = "../clippy_config" }
 arrayvec = { version = "0.7", default-features = false }
 itertools = "0.12"
 # FIXME(f16_f128): remove when no longer needed for parsing
 rustc_apfloat = "0.2.0"
+serde = { version = "1.0", features = ["derive"] }
 
 [package.metadata.rust-analyzer]
 # This crate uses #[feature(rustc_private)]
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
new file mode 100644
index 00000000000..61476a82ba0
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -0,0 +1,40 @@
+# `clippy-utils`
+
+Helpful tools for writing lints, provided as they are used in Clippy.
+
+## Usage
+
+This crate is only guaranteed to build with this `nightly` toolchain:
+
+<!-- begin autogenerated nightly -->
+```
+nightly-2024-11-28
+```
+<!-- end autogenerated nightly -->
+
+To use `clippy-utils` in your lint, add the following to your `Cargo.toml`:
+
+```
+clippy_utils = "0.1.XY"
+```
+
+`XY` is the version of the nightly toolchain above and can be determined with `rustc +nightly-YYYY-MM-DD -V`.
+
+## :warning: Stability :warning:
+
+No stability guarantees are made for this crate! Use at your own risk.
+
+Function signatures can change or be removed without replacement without any prior notice.
+
+## LICENSE
+
+<!-- REUSE-IgnoreStart -->
+
+Copyright 2014-2024 The Rust Project Developers
+
+Licensed under the Apache License, Version 2.0
+<[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
+<[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your option. Files in the project may
+not be copied, modified, or distributed except according to those terms.
+
+<!-- REUSE-IgnoreEnd -->
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index c90f4a6ebfe..620a9b56eb5 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
     match (l, r) {
         (Empty, Empty) => true,
         (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
-        (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re),
-        (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind,
+        (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re),
+        (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind,
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index edc9c6ccdff..b2a6657baad 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -27,7 +27,10 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, DeprecationStatus)] = &[
     ("cyclomatic_complexity", DeprecationStatus::Replaced("cognitive_complexity")),
     ("dump",                  DeprecationStatus::None),
     ("msrv",                  DeprecationStatus::None),
+    // The following attributes are for the 3rd party crate authors.
+    // See book/src/attribs.md
     ("has_significant_drop",  DeprecationStatus::None),
+    ("format_args",           DeprecationStatus::None),
 ];
 
 pub struct LimitStack {
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 52c98646289..43ddf06730d 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -226,7 +226,7 @@ impl Constant<'_> {
                     .zip(r)
                     .zip(tys)
                     .map(|((li, ri), cmp_type)| Self::partial_cmp(tcx, cmp_type, li, ri))
-                    .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+                    .find(|r| r.is_none_or(|o| o != Ordering::Equal))
                     .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
                 _ => None,
             },
@@ -236,7 +236,7 @@ impl Constant<'_> {
                 };
                 iter::zip(l, r)
                     .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
-                    .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+                    .find(|r| r.is_none_or(|o| o != Ordering::Equal))
                     .unwrap_or_else(|| Some(l.len().cmp(&r.len())))
             },
             (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => {
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 11bbe734844..d216879cbd2 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -8,7 +8,7 @@ use crate::ty::is_type_diagnostic_item;
 
 use rustc_ast::ast;
 use rustc_hir as hir;
-use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath};
+use rustc_hir::{Arm, Block, Expr, ExprKind, StructTailExpr, HirId, LoopSource, MatchSource, Node, Pat, QPath};
 use rustc_lint::LateContext;
 use rustc_span::{Span, sym, symbol};
 
@@ -236,7 +236,7 @@ impl<'a> Range<'a> {
                     limits: ast::RangeLimits::Closed,
                 })
             },
-            ExprKind::Struct(path, fields, None) => match (path, fields) {
+            ExprKind::Struct(path, fields, StructTailExpr::None) => match (path, fields) {
                 (QPath::LangItem(hir::LangItem::RangeFull, ..), []) => Some(Range {
                     start: None,
                     end: None,
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 920562f4b93..4be4340862d 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -10,7 +10,7 @@ use rustc_hir::{
     AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
     ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
     LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
-    TyKind,
+    TyKind, StructTailExpr,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::LateContext;
@@ -380,7 +380,12 @@ impl HirEqInterExpr<'_, '_, '_> {
             (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)),
             (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
                 self.eq_qpath(l_path, r_path)
-                    && both(lo.as_ref(), ro.as_ref(), |l, r| self.eq_expr(l, r))
+                    && match (lo, ro) {
+                        (StructTailExpr::Base(l),StructTailExpr::Base(r)) => self.eq_expr(l, r),
+                        (StructTailExpr::None, StructTailExpr::None) => true,
+                        (StructTailExpr::DefaultFields(_), StructTailExpr::DefaultFields(_)) => true,
+                        _ => false,
+                    }
                     && over(lf, rf, |l, r| self.eq_expr_field(l, r))
             },
             (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
@@ -539,7 +544,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool {
         if left.parenthesized == right.parenthesized {
             over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
-                && over(left.constraints, right.constraints, |l, r| self.eq_assoc_type_binding(l, r))
+                && over(left.constraints, right.constraints, |l, r| self.eq_assoc_eq_constraint(l, r))
         } else {
             false
         }
@@ -596,12 +601,13 @@ impl HirEqInterExpr<'_, '_, '_> {
         }
     }
 
-    fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool {
+    /// Checks whether two constraints designate the same equality constraint (same name, and same
+    /// type or const).
+    fn eq_assoc_eq_constraint(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool {
+        // TODO: this could be extended to check for identical associated item bound constraints
         left.ident.name == right.ident.name
-            && self.eq_ty(
-                left.ty().expect("expected assoc type binding"),
-                right.ty().expect("expected assoc type binding"),
-            )
+            && (both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r))
+                || both_some_and(left.ct(), right.ct(), |l, r| self.eq_const_arg(l, r)))
     }
 
     fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
@@ -721,6 +727,11 @@ pub fn both<X>(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bo
         .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y)))
 }
 
+/// Checks if the two `Option`s are both `Some` and pass the predicate function.
+pub fn both_some_and<X, Y>(l: Option<X>, r: Option<Y>, mut pred: impl FnMut(X, Y) -> bool) -> bool {
+    l.is_some_and(|l| r.is_some_and(|r| pred(l, r)))
+}
+
 /// Checks if two slices are equal as per `eq_fn`.
 pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool {
     left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y))
@@ -1011,7 +1022,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_expr(f.expr);
                 }
 
-                if let Some(e) = *expr {
+                if let StructTailExpr::Base(e) = *expr {
                     self.hash_expr(e);
                 }
             },
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 82699211489..8d48cdd3cbb 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -50,6 +50,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
+extern crate smallvec;
 
 #[macro_use]
 pub mod sym_helper;
@@ -65,6 +66,7 @@ pub mod higher;
 mod hir_utils;
 pub mod macros;
 pub mod mir;
+pub mod msrvs;
 pub mod numeric_literal;
 pub mod paths;
 pub mod ptr;
@@ -89,7 +91,6 @@ use std::hash::BuildHasherDefault;
 use std::iter::{once, repeat};
 use std::sync::{Mutex, MutexGuard, OnceLock};
 
-use clippy_config::types::DisallowedPath;
 use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_data_structures::fx::FxHashMap;
@@ -97,7 +98,7 @@ use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
 use rustc_hir::definitions::{DefPath, DefPathData};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
@@ -116,8 +117,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{
-    self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy,
-    Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture,
+    self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, Ty, TyCtxt,
+    TypeVisitableExt, UintTy, UpvarCapture,
 };
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
@@ -748,18 +749,6 @@ pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item =
     def_path_res(tcx, path).into_iter().filter_map(|res| res.opt_def_id())
 }
 
-/// Creates a map of disallowed items to the reason they were disallowed.
-pub fn create_disallowed_map(
-    tcx: TyCtxt<'_>,
-    disallowed: &'static [DisallowedPath],
-) -> DefIdMap<(&'static str, Option<&'static str>)> {
-    disallowed
-        .iter()
-        .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x.reason()))
-        .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason))))
-        .collect()
-}
-
 /// Convenience function to get the `DefId` of a trait by path.
 /// It could be a trait or trait alias.
 ///
@@ -1581,7 +1570,7 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
 pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
     if let Some(Range { start, end, limits }) = Range::hir(expr) {
-        let start_is_none_or_min = start.map_or(true, |start| {
+        let start_is_none_or_min = start.is_none_or(|start| {
             if let rustc_ty::Adt(_, subst) = ty.kind()
                 && let bnd_ty = subst.type_at(0)
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
@@ -1593,7 +1582,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 false
             }
         });
-        let end_is_none_or_max = end.map_or(true, |end| match limits {
+        let end_is_none_or_max = end.is_none_or(|end| match limits {
             RangeLimits::Closed => {
                 if let rustc_ty::Adt(_, subst) = ty.kind()
                     && let bnd_ty = subst.type_at(0)
@@ -2715,10 +2704,10 @@ pub enum DefinedTy<'tcx> {
     /// Used for function signatures, and constant and static values. The type is
     /// in the context of its definition site. We also track the `def_id` of its
     /// definition site.
-    /// 
+    ///
     /// WARNING: As the `ty` in in the scope of the definition, not of the function
     /// using it, you must be very careful with how you use it. Using it in the wrong
-    /// scope easily results in ICEs. 
+    /// scope easily results in ICEs.
     Mir {
         def_site_def_id: Option<DefId>,
         ty: Binder<'tcx, Ty<'tcx>>,
@@ -2844,7 +2833,7 @@ impl<'tcx> ExprUseNode<'tcx> {
             Self::ConstStatic(id) => Some(DefinedTy::Mir {
                 def_site_def_id: Some(id.def_id.to_def_id()),
                 ty: Binder::dummy(cx.tcx.type_of(id).instantiate_identity()),
-        }),
+            }),
             Self::Return(id) => {
                 if let Node::Expr(Expr {
                     kind: ExprKind::Closure(c),
@@ -2857,7 +2846,10 @@ impl<'tcx> ExprUseNode<'tcx> {
                     }
                 } else {
                     let ty = cx.tcx.fn_sig(id).instantiate_identity().output();
-                    Some(DefinedTy::Mir { def_site_def_id: Some(id.def_id.to_def_id()), ty })
+                    Some(DefinedTy::Mir {
+                        def_site_def_id: Some(id.def_id.to_def_id()),
+                        ty,
+                    })
                 }
             },
             Self::Field(field) => match get_parent_expr_for_hir(cx, field.hir_id) {
@@ -2874,8 +2866,8 @@ impl<'tcx> ExprUseNode<'tcx> {
                             .map(|f| (adt, f))
                     })
                     .map(|(adt, field_def)| DefinedTy::Mir {
-                            def_site_def_id: Some(adt.did()),
-                            ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()),
+                        def_site_def_id: Some(adt.did()),
+                        ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()),
                     }),
                 _ => None,
             },
@@ -2885,9 +2877,9 @@ impl<'tcx> ExprUseNode<'tcx> {
                 Some(match hir_ty {
                     Some(hir_ty) => DefinedTy::Hir(hir_ty),
                     None => DefinedTy::Mir {
-                        def_site_def_id:  sig.predicates_id(),
+                        def_site_def_id: sig.predicates_id(),
                         ty,
-                    }
+                    },
                 })
             },
             Self::MethodArg(id, _, i) => {
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 9c4d19ac1f1..45beb146eb6 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,5 +1,6 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
+use crate::get_unique_attr;
 use crate::visitors::{Descend, for_each_expr_without_closures};
 
 use arrayvec::ArrayVec;
@@ -7,7 +8,7 @@ use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{Lrc, OnceLock};
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
-use rustc_lint::LateContext;
+use rustc_lint::{LateContext, LintContext};
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
 use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym};
@@ -36,7 +37,9 @@ pub fn is_format_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool {
     if let Some(name) = cx.tcx.get_diagnostic_name(macro_def_id) {
         FORMAT_MACRO_DIAG_ITEMS.contains(&name)
     } else {
-        false
+        // Allow users to tag any macro as being format!-like
+        // TODO: consider deleting FORMAT_MACRO_DIAG_ITEMS and using just this method
+        get_unique_attr(cx.sess(), cx.tcx.get_attrs_unchecked(macro_def_id), "format_args").is_some()
     }
 }
 
@@ -93,7 +96,7 @@ pub fn expn_is_local(expn: ExpnId) -> bool {
     std::iter::once((expn, data))
         .chain(backtrace)
         .find_map(|(_, data)| data.macro_def_id)
-        .map_or(true, DefId::is_local)
+        .is_none_or(DefId::is_local)
 }
 
 /// Returns an iterator of macro expansions that created the given span.
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index 6b3078f52af..17e6558a41c 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -2,7 +2,7 @@ use super::possible_origin::PossibleOriginVisitor;
 use super::transitive_relation::TransitiveRelation;
 use crate::ty::is_copy;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::bit_set::{BitSet, HybridBitSet};
+use rustc_index::bit_set::BitSet;
 use rustc_lint::LateContext;
 use rustc_middle::mir::visit::Visitor as _;
 use rustc_middle::mir::{self, Mutability};
@@ -21,14 +21,14 @@ struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
     possible_borrower: TransitiveRelation,
     body: &'b mir::Body<'tcx>,
     cx: &'a LateContext<'tcx>,
-    possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+    possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>,
 }
 
 impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
     fn new(
         cx: &'a LateContext<'tcx>,
         body: &'b mir::Body<'tcx>,
-        possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+        possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>,
     ) -> Self {
         Self {
             possible_borrower: TransitiveRelation::default(),
@@ -119,7 +119,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> {
             let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
                 .iter()
                 .filter_map(|r| self.possible_origin.get(r))
-                .flat_map(HybridBitSet::iter)
+                .flat_map(BitSet::iter)
                 .collect();
 
             if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
@@ -171,7 +171,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
 #[allow(clippy::module_name_repetitions)]
 pub struct PossibleBorrowerMap<'b, 'tcx> {
     /// Mapping `Local -> its possible borrowers`
-    pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+    pub map: FxHashMap<mir::Local, BitSet<mir::Local>>,
     maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
     // Caches to avoid allocation of `BitSet` on every query
     pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs
index 4157b3f4930..47b93aad20c 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs
@@ -1,7 +1,7 @@
 use super::transitive_relation::TransitiveRelation;
 use crate::ty::is_copy;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::bit_set::HybridBitSet;
+use rustc_index::bit_set::BitSet;
 use rustc_lint::LateContext;
 use rustc_middle::mir;
 
@@ -22,7 +22,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> {
+    pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, BitSet<mir::Local>> {
         let mut map = FxHashMap::default();
         for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
             if is_copy(cx, self.body.local_decls[row].ty) {
diff --git a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs
index 7fe2960739f..74d1f60af71 100644
--- a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::bit_set::HybridBitSet;
+use rustc_index::bit_set::BitSet;
 use rustc_middle::mir;
 
 #[derive(Default)]
@@ -12,8 +12,8 @@ impl TransitiveRelation {
         self.relations.entry(a).or_default().push(b);
     }
 
-    pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> {
-        let mut seen = HybridBitSet::new_empty(domain_size);
+    pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> BitSet<mir::Local> {
+        let mut seen = BitSet::new_empty(domain_size);
         let mut stack = vec![a];
         while let Some(u) = stack.pop() {
             if let Some(edges) = self.relations.get(&u) {
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 764ca8fb50a..1eb7d54e133 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -121,7 +121,7 @@ impl Msrv {
     }
 
     pub fn meets(&self, required: RustcVersion) -> bool {
-        self.current().map_or(true, |msrv| msrv >= required)
+        self.current().is_none_or(|msrv| msrv >= required)
     }
 
     fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 11a98b02f33..bb40a9430a7 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -36,7 +36,7 @@ pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"];
 pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"];
 
 // Paths in clippy itself
-pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
+pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
 
 // Paths in external crates
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
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 3c9ea4bfaf4..df3f10d6179 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
@@ -3,7 +3,7 @@
 // of terminologies might not be relevant in the context of Clippy. Note that its behavior might
 // differ from the time of `rustc` even if the name stays the same.
 
-use clippy_config::msrvs::{self, Msrv};
+use crate::msrvs::{self, Msrv};
 use hir::LangItem;
 use rustc_attr::StableSince;
 use rustc_const_eval::check_consts::ConstCx;
@@ -409,8 +409,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
             return false;
         }
 
-        let (infcx, param_env) =
-            tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx));
+        let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx));
         // FIXME(const_trait_impl) constness
         let obligation = Obligation::new(
             tcx,
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 03e1a814a86..260d1b801e3 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain;
 
 /// Checks if the given type implements copy.
 pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
+    cx.type_is_copy_modulo_regions(ty)
 }
 
 /// This checks whether a given type is known to implement Debug.
@@ -226,7 +226,14 @@ pub fn implements_trait<'tcx>(
     trait_id: DefId,
     args: &[GenericArg<'tcx>],
 ) -> bool {
-    implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, trait_id, None, args.iter().map(|&x| Some(x)))
+    implements_trait_with_env_from_iter(
+        cx.tcx,
+        cx.typing_env(),
+        ty,
+        trait_id,
+        None,
+        args.iter().map(|&x| Some(x)),
+    )
 }
 
 /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
@@ -1262,7 +1269,8 @@ pub fn make_normalized_projection_with_regions<'tcx>(
         }
         let cause = ObligationCause::dummy();
         let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
-        match infcx.at(&cause, param_env)
+        match infcx
+            .at(&cause, param_env)
             .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args))
         {
             Ok(ty) => Some(ty.value),
@@ -1278,7 +1286,10 @@ pub fn make_normalized_projection_with_regions<'tcx>(
 pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     let cause = ObligationCause::dummy();
     let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
-    infcx.at(&cause, param_env).query_normalize(ty).map_or(ty, |ty| ty.value)
+    infcx
+        .at(&cause, param_env)
+        .query_normalize(ty)
+        .map_or(ty, |ty| ty.value)
 }
 
 /// Checks if the type is `core::mem::ManuallyDrop<_>`
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index c8c25456f69..37f72966892 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -27,7 +27,7 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
 }
 
 pub fn is_potentially_mutated<'tcx>(variable: HirId, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
-    mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&variable))
+    mutated_variables(expr, cx).is_none_or(|mutated| mutated.contains(&variable))
 }
 
 pub fn is_potentially_local_place(local_id: HirId, place: &Place<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index a79be5ca7d4..351e619d7b1 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -7,7 +7,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
 use rustc_hir::{
     AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath,
-    Safety, Stmt, UnOp, UnsafeSource,
+    Safety, Stmt, UnOp, UnsafeSource, StructTailExpr,
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
@@ -663,7 +663,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
                 for field in fields {
                     helper(typeck, true, field.expr, f)?;
                 }
-                if let Some(default) = default {
+                if let StructTailExpr::Base(default) = default {
                     helper(typeck, false, default, f)?;
                 }
             },
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index e32e0cb3604..fb159ca2ae0 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,6 @@
 [toolchain]
-channel = "nightly-2024-11-14"
+# begin autogenerated nightly
+channel = "nightly-2024-11-28"
+# end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index c66837dc998..32ee668cda1 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -236,7 +236,8 @@ pub fn main() {
             let mut args: Vec<String> = orig_args.clone();
             pass_sysroot_env_if_given(&mut args, sys_root_env);
 
-            return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
+            rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
+            return Ok(());
         }
 
         if orig_args.iter().any(|a| a == "--version" || a == "-V") {
@@ -296,12 +297,13 @@ pub fn main() {
             args.extend(clippy_args);
             rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var })
                 .set_using_internal_features(using_internal_features)
-                .run()
+                .run();
         } else {
             rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var })
                 .set_using_internal_features(using_internal_features)
-                .run()
+                .run();
         }
+        return Ok(());
     }))
 }
 
diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
index 9b5bf736f13..928596d0809 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
+++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
@@ -8,8 +8,8 @@ extern crate rustc_lint;
 extern crate rustc_middle;
 #[macro_use]
 extern crate rustc_session;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::extract_msrv_attr;
+use clippy_utils::msrvs::Msrv;
 use rustc_hir::Expr;
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 
diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
index c5bde47e4ce..50b28648ccc 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
+++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
@@ -8,8 +8,8 @@ extern crate rustc_lint;
 extern crate rustc_middle;
 #[macro_use]
 extern crate rustc_session;
-use clippy_config::msrvs::Msrv;
 use clippy_utils::extract_msrv_attr;
+use clippy_utils::msrvs::Msrv;
 use rustc_hir::Expr;
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.rs b/src/tools/clippy/tests/ui/crashes/ice-10645.rs
deleted file mode 100644
index 6e126aff751..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-10645.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@compile-flags: --cap-lints=warn
-// https://github.com/rust-lang/rust-clippy/issues/10645
-
-#![warn(clippy::future_not_send)]
-pub async fn bar<'a, T: 'a>(_: T) {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
deleted file mode 100644
index 0269072b88b..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: future cannot be sent between threads safely
-  --> tests/ui/crashes/ice-10645.rs:5:1
-   |
-LL | pub async fn bar<'a, T: 'a>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `bar` is not `Send`
-   |
-note: captured value is not `Send`
-  --> tests/ui/crashes/ice-10645.rs:5:29
-   |
-LL | pub async fn bar<'a, T: 'a>(_: T) {}
-   |                             ^ has type `T` which is not `Send`
-   = note: `T` doesn't implement `std::marker::Send`
-   = note: `-D clippy::future-not-send` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
-
-warning: 1 warning emitted
-
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
new file mode 100644
index 00000000000..c85f384fd6e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -0,0 +1,295 @@
+#![allow(dead_code)]
+
+use std::collections::HashMap;
+
+#[derive(Default)]
+struct FooDefault<'a> {
+    a: bool,
+    b: i32,
+    c: u64,
+    d: Vec<i32>,
+    e: FooND1,
+    f: FooND2,
+    g: HashMap<i32, i32>,
+    h: (i32, Vec<i32>),
+    i: [Vec<i32>; 3],
+    j: [i32; 5],
+    k: Option<i32>,
+    l: &'a [i32],
+}
+
+
+#[derive(Default)]
+struct TupleDefault(bool, i32, u64);
+
+
+struct FooND1 {
+    a: bool,
+}
+
+impl std::default::Default for FooND1 {
+    fn default() -> Self {
+        Self { a: true }
+    }
+}
+
+struct FooND2 {
+    a: i32,
+}
+
+impl std::default::Default for FooND2 {
+    fn default() -> Self {
+        Self { a: 5 }
+    }
+}
+
+struct FooNDNew {
+    a: bool,
+}
+
+impl FooNDNew {
+    fn new() -> Self {
+        Self { a: true }
+    }
+}
+
+impl Default for FooNDNew {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+struct FooNDVec(Vec<i32>);
+
+impl Default for FooNDVec {
+    fn default() -> Self {
+        Self(vec![5, 12])
+    }
+}
+
+#[derive(Default)]
+struct StrDefault<'a>(&'a str);
+
+
+#[derive(Default)]
+struct AlreadyDerived(i32, bool);
+
+macro_rules! mac {
+    () => {
+        0
+    };
+    ($e:expr) => {
+        struct X(u32);
+        impl Default for X {
+            fn default() -> Self {
+                Self($e)
+            }
+        }
+    };
+}
+
+mac!(0);
+
+#[derive(Default)]
+struct Y(u32);
+
+struct RustIssue26925<T> {
+    a: Option<T>,
+}
+
+// We should watch out for cases where a manual impl is needed because a
+// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
+// For example, a struct with Option<T> does not require T: Default, but a derive adds
+// that type bound anyways. So until #26925 get fixed we should disable lint
+// for the following case
+impl<T> Default for RustIssue26925<T> {
+    fn default() -> Self {
+        Self { a: None }
+    }
+}
+
+struct SpecializedImpl<A, B> {
+    a: A,
+    b: B,
+}
+
+impl<T: Default> Default for SpecializedImpl<T, T> {
+    fn default() -> Self {
+        Self {
+            a: T::default(),
+            b: T::default(),
+        }
+    }
+}
+
+#[derive(Default)]
+struct WithoutSelfCurly {
+    a: bool,
+}
+
+
+#[derive(Default)]
+struct WithoutSelfParan(bool);
+
+
+// https://github.com/rust-lang/rust-clippy/issues/7655
+
+pub struct SpecializedImpl2<T> {
+    v: Vec<T>,
+}
+
+impl Default for SpecializedImpl2<String> {
+    fn default() -> Self {
+        Self { v: Vec::new() }
+    }
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/7654
+
+pub struct Color {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+}
+
+/// `#000000`
+impl Default for Color {
+    fn default() -> Self {
+        Color { r: 0, g: 0, b: 0 }
+    }
+}
+
+pub struct Color2 {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+}
+
+impl Default for Color2 {
+    /// `#000000`
+    fn default() -> Self {
+        Self { r: 0, g: 0, b: 0 }
+    }
+}
+
+#[derive(Default)]
+pub struct RepeatDefault1 {
+    a: [i8; 32],
+}
+
+
+pub struct RepeatDefault2 {
+    a: [i8; 33],
+}
+
+impl Default for RepeatDefault2 {
+    fn default() -> Self {
+        RepeatDefault2 { a: [0; 33] }
+    }
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/7753
+
+pub enum IntOrString {
+    Int(i32),
+    String(String),
+}
+
+impl Default for IntOrString {
+    fn default() -> Self {
+        IntOrString::Int(0)
+    }
+}
+
+#[derive(Default)]
+pub enum SimpleEnum {
+    Foo,
+    #[default]
+    Bar,
+}
+
+
+pub enum NonExhaustiveEnum {
+    Foo,
+    #[non_exhaustive]
+    Bar,
+}
+
+impl Default for NonExhaustiveEnum {
+    fn default() -> Self {
+        NonExhaustiveEnum::Bar
+    }
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/10396
+
+#[derive(Default)]
+struct DefaultType;
+
+struct GenericType<T = DefaultType> {
+    t: T,
+}
+
+impl Default for GenericType {
+    fn default() -> Self {
+        Self { t: Default::default() }
+    }
+}
+
+struct InnerGenericType<T> {
+    t: T,
+}
+
+impl Default for InnerGenericType<DefaultType> {
+    fn default() -> Self {
+        Self { t: Default::default() }
+    }
+}
+
+struct OtherGenericType<T = DefaultType> {
+    inner: InnerGenericType<T>,
+}
+
+impl Default for OtherGenericType {
+    fn default() -> Self {
+        Self {
+            inner: Default::default(),
+        }
+    }
+}
+
+mod issue10158 {
+    pub trait T {}
+
+    #[derive(Default)]
+    pub struct S {}
+    impl T for S {}
+
+    pub struct Outer {
+        pub inner: Box<dyn T>,
+    }
+
+    impl Default for Outer {
+        fn default() -> Self {
+            Outer {
+                // Box::<S>::default() adjusts to Box<dyn T>
+                inner: Box::<S>::default(),
+            }
+        }
+    }
+}
+
+mod issue11368 {
+    pub struct A {
+        a: u32,
+    }
+
+    impl Default for A {
+        #[track_caller]
+        fn default() -> Self {
+            Self { a: 0 }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index 58f7771b627..21d73ba8b77 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -1,7 +1,5 @@
 #![allow(dead_code)]
 
-//@no-rustfix: need to change the suggestion to a multipart suggestion
-
 use std::collections::HashMap;
 
 struct FooDefault<'a> {
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index d3adfa60e10..c22569145bd 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -1,5 +1,5 @@
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:22:1
+  --> tests/ui/derivable_impls.rs:20:1
    |
 LL | / impl std::default::Default for FooDefault<'_> {
 LL | |     fn default() -> Self {
@@ -12,15 +12,14 @@ LL | | }
    |
    = note: `-D clippy::derivable-impls` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::derivable_impls)]`
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct FooDefault<'a> {
+LL ~ struct FooDefault<'a> {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:43:1
+  --> tests/ui/derivable_impls.rs:41:1
    |
 LL | / impl std::default::Default for TupleDefault {
 LL | |     fn default() -> Self {
@@ -29,15 +28,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct TupleDefault(bool, i32, u64);
+LL ~ struct TupleDefault(bool, i32, u64);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:95:1
+  --> tests/ui/derivable_impls.rs:93:1
    |
 LL | / impl Default for StrDefault<'_> {
 LL | |     fn default() -> Self {
@@ -46,15 +44,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct StrDefault<'a>(&'a str);
+LL ~ struct StrDefault<'a>(&'a str);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:121:1
+  --> tests/ui/derivable_impls.rs:119:1
    |
 LL | / impl Default for Y {
 LL | |     fn default() -> Self {
@@ -63,15 +60,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct Y(u32);
+LL ~ struct Y(u32);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:160:1
+  --> tests/ui/derivable_impls.rs:158:1
    |
 LL | / impl Default for WithoutSelfCurly {
 LL | |     fn default() -> Self {
@@ -80,15 +76,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct WithoutSelfCurly {
+LL ~ struct WithoutSelfCurly {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:168:1
+  --> tests/ui/derivable_impls.rs:166:1
    |
 LL | / impl Default for WithoutSelfParan {
 LL | |     fn default() -> Self {
@@ -97,15 +92,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | struct WithoutSelfParan(bool);
+LL ~ struct WithoutSelfParan(bool);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:218:1
+  --> tests/ui/derivable_impls.rs:216:1
    |
 LL | / impl Default for RepeatDefault1 {
 LL | |     fn default() -> Self {
@@ -114,15 +108,14 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it
+help: replace the manual implementation with a derive attribute
    |
 LL + #[derive(Default)]
-LL | pub struct RepeatDefault1 {
+LL ~ pub struct RepeatDefault1 {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:252:1
+  --> tests/ui/derivable_impls.rs:250:1
    |
 LL | / impl Default for SimpleEnum {
 LL | |     fn default() -> Self {
@@ -131,14 +124,11 @@ LL | |     }
 LL | | }
    | |_^
    |
-   = help: remove the manual implementation...
-help: ...and instead derive it...
+help: replace the manual implementation with a derive attribute and mark the default variant
    |
 LL + #[derive(Default)]
-LL | pub enum SimpleEnum {
-   |
-help: ...and mark the default variant
-   |
+LL ~ pub enum SimpleEnum {
+LL |     Foo,
 LL ~     #[default]
 LL ~     Bar,
    |
diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed
new file mode 100644
index 00000000000..d4ae810d738
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed
@@ -0,0 +1,40 @@
+#![warn(clippy::doc_include_without_cfg)]
+// Should not lint.
+#![doc(html_playground_url = "https://playground.example.com/")]
+#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg
+// Should not lint.
+#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))]
+#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))]
+#![doc = "some doc"]
+//! more doc
+
+macro_rules! man_link {
+    ($a:literal, $b:literal) => {
+        concat!($a, $b)
+    };
+}
+
+// Should not lint!
+macro_rules! tst {
+    ($(#[$attr:meta])*) => {
+        $(#[$attr])*
+        fn blue() {
+            println!("Hello, world!");
+        }
+    }
+}
+
+tst! {
+    /// This is a test with no included file
+}
+
+#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg
+// Should not lint.
+#[doc = man_link!("bla", "blob")]
+#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))]
+#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]
+#[doc = "some doc"]
+/// more doc
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs
new file mode 100644
index 00000000000..c82f6bf2035
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs
@@ -0,0 +1,40 @@
+#![warn(clippy::doc_include_without_cfg)]
+// Should not lint.
+#![doc(html_playground_url = "https://playground.example.com/")]
+#![doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg
+// Should not lint.
+#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))]
+#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))]
+#![doc = "some doc"]
+//! more doc
+
+macro_rules! man_link {
+    ($a:literal, $b:literal) => {
+        concat!($a, $b)
+    };
+}
+
+// Should not lint!
+macro_rules! tst {
+    ($(#[$attr:meta])*) => {
+        $(#[$attr])*
+        fn blue() {
+            println!("Hello, world!");
+        }
+    }
+}
+
+tst! {
+    /// This is a test with no included file
+}
+
+#[doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg
+// Should not lint.
+#[doc = man_link!("bla", "blob")]
+#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))]
+#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]
+#[doc = "some doc"]
+/// more doc
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr
new file mode 100644
index 00000000000..17ea53c7c31
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr
@@ -0,0 +1,17 @@
+error: included a file in documentation unconditionally
+  --> tests/ui/doc/doc_include_without_cfg.rs:4:1
+   |
+LL | #![doc = include_str!("../approx_const.rs")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))]`
+   |
+   = note: `-D clippy::doc-include-without-cfg` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_include_without_cfg)]`
+
+error: included a file in documentation unconditionally
+  --> tests/ui/doc/doc_include_without_cfg.rs:31:1
+   |
+LL | #[doc = include_str!("../approx_const.rs")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
index 17d2ed9f50c..aa964af3fc2 100644
--- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
@@ -134,4 +134,11 @@ struct Human<'a> {
     pub name: &'a str,
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/13578
+mod issue_13578 {
+    pub trait Foo {}
+
+    impl<'a, T: 'a> Foo for Option<T> where &'a T: Foo {}
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.rs b/src/tools/clippy/tests/ui/fn_address_comparisons.rs
deleted file mode 100644
index 35535bd4fdd..00000000000
--- a/src/tools/clippy/tests/ui/fn_address_comparisons.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use std::fmt::Debug;
-use std::ptr;
-use std::rc::Rc;
-use std::sync::Arc;
-
-fn a() {}
-
-#[warn(clippy::fn_address_comparisons)]
-fn main() {
-    type F = fn();
-    let f: F = a;
-    let g: F = f;
-
-    // These should fail:
-    let _ = f == a;
-    //~^ ERROR: comparing with a non-unique address of a function item
-    //~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings`
-    let _ = f != a;
-    //~^ ERROR: comparing with a non-unique address of a function item
-
-    // These should be fine:
-    let _ = f == g;
-}
diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr b/src/tools/clippy/tests/ui/fn_address_comparisons.stderr
deleted file mode 100644
index e6de7e35807..00000000000
--- a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error: comparing with a non-unique address of a function item
-  --> tests/ui/fn_address_comparisons.rs:15:13
-   |
-LL |     let _ = f == a;
-   |             ^^^^^^
-   |
-   = note: `-D clippy::fn-address-comparisons` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]`
-
-error: comparing with a non-unique address of a function item
-  --> tests/ui/fn_address_comparisons.rs:18:13
-   |
-LL |     let _ = f != a;
-   |             ^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs
index f04715f4f01..7590de3751a 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.rs
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs
@@ -119,3 +119,32 @@ fn test2() {
         format!("something failed at {}", Location::caller())
     );
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn user_format() {
+    let error = Error::new(ErrorKind::Other, "bad thing");
+    let x = 'x';
+
+    usr_println!(true, "error: {}", format!("boom at {}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+    usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller()));
+    //~^ ERROR: `format!` in `usr_println!` args
+}
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.stderr b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
index 20cd0bb8c55..1b4b683fd6c 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
@@ -174,5 +174,68 @@ LL |     panic!("error: {}", format!("something failed at {}", Location::caller(
    = help: combine the `format!(..)` arguments with the outer `panic!(..)` call
    = help: or consider changing `format!` to `format_args!`
 
-error: aborting due to 18 previous errors
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:136:5
+   |
+LL |     usr_println!(true, "error: {}", format!("boom at {}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:138:5
+   |
+LL |     usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:140:5
+   |
+LL |     usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:142:5
+   |
+LL |     usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:144:5
+   |
+LL |     usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:146:5
+   |
+LL |     usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: `format!` in `usr_println!` args
+  --> tests/ui/format_args_unfixable.rs:148:5
+   |
+LL |     usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
+   = help: or consider changing `format!` to `format_args!`
+
+error: aborting due to 25 previous errors
 
diff --git a/src/tools/clippy/tests/ui/future_not_send.rs b/src/tools/clippy/tests/ui/future_not_send.rs
index 9274340b5ca..626ee6de9e4 100644
--- a/src/tools/clippy/tests/ui/future_not_send.rs
+++ b/src/tools/clippy/tests/ui/future_not_send.rs
@@ -1,6 +1,7 @@
 #![warn(clippy::future_not_send)]
 
 use std::cell::Cell;
+use std::future::Future;
 use std::rc::Rc;
 use std::sync::Arc;
 
@@ -63,6 +64,22 @@ where
     t
 }
 
+async fn maybe_send_generic_future<T>(t: T) -> T {
+    async { true }.await;
+    t
+}
+
+async fn maybe_send_generic_future2<F: Fn() -> Fut, Fut: Future>(f: F) {
+    async { true }.await;
+    let res = f();
+    async { true }.await;
+}
+
+async fn generic_future_always_unsend<T>(_: Rc<T>) {
+    //~^ ERROR: future cannot be sent between threads safely
+    async { true }.await;
+}
+
 async fn generic_future_send<T>(t: T)
 where
     T: Send,
@@ -71,7 +88,6 @@ where
 }
 
 async fn unclear_future<T>(t: T) {}
-//~^ ERROR: future cannot be sent between threads safely
 
 fn main() {
     let rc = Rc::new([1, 2, 3]);
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index 67677d6367a..3807c747013 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -1,11 +1,11 @@
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:7:1
+  --> tests/ui/future_not_send.rs:8:1
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/future_not_send.rs:9:20
+  --> tests/ui/future_not_send.rs:10:20
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -14,7 +14,7 @@ LL |     async { true }.await
    |                    ^^^^^ await occurs here, with `rc` maybe used later
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> tests/ui/future_not_send.rs:7:39
+  --> tests/ui/future_not_send.rs:8:39
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                       ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
@@ -23,13 +23,13 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:12:1
+  --> tests/ui/future_not_send.rs:13:1
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/future_not_send.rs:14:20
+  --> tests/ui/future_not_send.rs:15:20
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -39,45 +39,45 @@ LL |     async { true }.await;
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:21:1
+  --> tests/ui/future_not_send.rs:22:1
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> tests/ui/future_not_send.rs:21:26
+  --> tests/ui/future_not_send.rs:22:26
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> tests/ui/future_not_send.rs:21:40
+  --> tests/ui/future_not_send.rs:22:40
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:26:1
+  --> tests/ui/future_not_send.rs:27:1
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> tests/ui/future_not_send.rs:26:29
+  --> tests/ui/future_not_send.rs:27:29
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    |                             ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:38:5
+  --> tests/ui/future_not_send.rs:39:5
    |
 LL |     async fn private_future(&self) -> usize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/future_not_send.rs:40:24
+  --> tests/ui/future_not_send.rs:41:24
    |
 LL |     async fn private_future(&self) -> usize {
    |                             ----- has type `&Dummy` which is not `Send`
@@ -87,20 +87,20 @@ LL |         async { true }.await;
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:44:5
+  --> tests/ui/future_not_send.rs:45:5
    |
 LL |     pub async fn public_future(&self) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
    |
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> tests/ui/future_not_send.rs:44:32
+  --> tests/ui/future_not_send.rs:45:32
    |
 LL |     pub async fn public_future(&self) {
    |                                ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:55:1
+  --> tests/ui/future_not_send.rs:56:1
    |
 LL | / async fn generic_future<T>(t: T) -> T
 LL | |
@@ -109,7 +109,7 @@ LL | |     T: Send,
    | |____________^ future returned by `generic_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/future_not_send.rs:61:20
+  --> tests/ui/future_not_send.rs:62:20
    |
 LL |     let rt = &t;
    |         -- has type `&T` which is not `Send`
@@ -118,17 +118,20 @@ LL |     async { true }.await;
    = note: `T` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:73:1
+  --> tests/ui/future_not_send.rs:78:1
    |
-LL | async fn unclear_future<T>(t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `unclear_future` is not `Send`
+LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send`
    |
-note: captured value is not `Send`
-  --> tests/ui/future_not_send.rs:73:28
+note: future is not `Send` as this value is used across an await
+  --> tests/ui/future_not_send.rs:80:20
    |
-LL | async fn unclear_future<T>(t: T) {}
-   |                            ^ has type `T` which is not `Send`
-   = note: `T` doesn't implement `std::marker::Send`
+LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
+   |                                          - has type `std::rc::Rc<T>` which is not `Send`
+LL |
+LL |     async { true }.await;
+   |                    ^^^^^ await occurs here, with `_` maybe used later
+   = note: `std::rc::Rc<T>` doesn't implement `std::marker::Send`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_let_mutex.stderr b/src/tools/clippy/tests/ui/if_let_mutex.edition2021.stderr
index 45df4ac4d67..984d6adbb2a 100644
--- a/src/tools/clippy/tests/ui/if_let_mutex.stderr
+++ b/src/tools/clippy/tests/ui/if_let_mutex.edition2021.stderr
@@ -1,5 +1,5 @@
 error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
-  --> tests/ui/if_let_mutex.rs:11:5
+  --> tests/ui/if_let_mutex.rs:16:5
    |
 LL |       if let Err(locked) = m.lock() {
    |       ^                    - this Mutex will remain locked for the entire `if let`-block...
@@ -19,7 +19,7 @@ LL | |     };
    = help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]`
 
 error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
-  --> tests/ui/if_let_mutex.rs:24:5
+  --> tests/ui/if_let_mutex.rs:29:5
    |
 LL |       if let Some(locked) = m.lock().unwrap().deref() {
    |       ^                     - this Mutex will remain locked for the entire `if let`-block...
@@ -37,7 +37,7 @@ LL | |     };
    = help: move the lock call outside of the `if let ...` expression
 
 error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
-  --> tests/ui/if_let_mutex.rs:46:5
+  --> tests/ui/if_let_mutex.rs:51:5
    |
 LL |       if let Ok(i) = mutex.lock() {
    |       ^              ----- this Mutex will remain locked for the entire `if let`-block...
@@ -54,7 +54,7 @@ LL | |     };
    = help: move the lock call outside of the `if let ...` expression
 
 error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
-  --> tests/ui/if_let_mutex.rs:55:5
+  --> tests/ui/if_let_mutex.rs:60:5
    |
 LL |       if let Ok(_) = m1.lock() {
    |       ^              -- this Mutex will remain locked for the entire `if let`-block...
diff --git a/src/tools/clippy/tests/ui/if_let_mutex.rs b/src/tools/clippy/tests/ui/if_let_mutex.rs
index bb0eadfca1c..80eee293989 100644
--- a/src/tools/clippy/tests/ui/if_let_mutex.rs
+++ b/src/tools/clippy/tests/ui/if_let_mutex.rs
@@ -1,3 +1,8 @@
+//@ compile-flags: -Zunstable-options
+
+//@revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
 #![warn(clippy::if_let_mutex)]
 #![allow(clippy::redundant_pattern_matching)]
 
@@ -9,7 +14,7 @@ fn do_stuff<T>(_: T) {}
 fn if_let() {
     let m = Mutex::new(1_u8);
     if let Err(locked) = m.lock() {
-        //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d
+        //~[edition2021]^ if_let_mutex
         do_stuff(locked);
     } else {
         let lock = m.lock().unwrap();
@@ -22,7 +27,7 @@ fn if_let() {
 fn if_let_option() {
     let m = Mutex::new(Some(0_u8));
     if let Some(locked) = m.lock().unwrap().deref() {
-        //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d
+        //~[edition2021]^ if_let_mutex
         do_stuff(locked);
     } else {
         let lock = m.lock().unwrap();
@@ -44,7 +49,7 @@ fn if_let_different_mutex() {
 
 fn mutex_ref(mutex: &Mutex<i32>) {
     if let Ok(i) = mutex.lock() {
-        //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d
+        //~[edition2021]^ if_let_mutex
         do_stuff(i);
     } else {
         let _x = mutex.lock();
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
index 754fe061c4a..014fbb85c7a 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -1,6 +1,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
-#![feature(const_trait_impl, abi_vectorcall)]
+#![feature(const_trait_impl)]
 
 use std::mem::transmute;
 
@@ -211,8 +211,4 @@ mod extern_fn {
     //~^ ERROR: this could be a `const fn`
     const extern "system-unwind" fn system_unwind() {}
     //~^ ERROR: this could be a `const fn`
-    pub const extern "vectorcall" fn std_call() {}
-    //~^ ERROR: this could be a `const fn`
-    pub const extern "vectorcall-unwind" fn std_call_unwind() {}
-    //~^ ERROR: this could be a `const fn`
 }
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
index 460be0733e0..4f7c2cbcf0b 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
-#![feature(const_trait_impl, abi_vectorcall)]
+#![feature(const_trait_impl)]
 
 use std::mem::transmute;
 
@@ -211,8 +211,4 @@ mod extern_fn {
     //~^ ERROR: this could be a `const fn`
     extern "system-unwind" fn system_unwind() {}
     //~^ ERROR: this could be a `const fn`
-    pub extern "vectorcall" fn std_call() {}
-    //~^ ERROR: this could be a `const fn`
-    pub extern "vectorcall-unwind" fn std_call_unwind() {}
-    //~^ ERROR: this could be a `const fn`
 }
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
index d553c522556..cc7dfd0888d 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -316,27 +316,5 @@ help: make the function `const`
 LL |     const extern "system-unwind" fn system_unwind() {}
    |     +++++
 
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5
-   |
-LL |     pub extern "vectorcall" fn std_call() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL |     pub const extern "vectorcall" fn std_call() {}
-   |         +++++
-
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5
-   |
-LL |     pub extern "vectorcall-unwind" fn std_call_unwind() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL |     pub const extern "vectorcall-unwind" fn std_call_unwind() {}
-   |         +++++
-
-error: aborting due to 26 previous errors
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_doc_crate.rs b/src/tools/clippy/tests/ui/missing_doc_crate.rs
index e00c7fbfed1..fdb23af279d 100644
--- a/src/tools/clippy/tests/ui/missing_doc_crate.rs
+++ b/src/tools/clippy/tests/ui/missing_doc_crate.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::missing_docs_in_private_items)]
+#![allow(clippy::doc_include_without_cfg)]
 #![doc = include_str!("../../README.md")]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed
index ed4b1c21915..ff7b233f004 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.fixed
+++ b/src/tools/clippy/tests/ui/redundant_guards.fixed
@@ -1,6 +1,6 @@
 //@aux-build:proc_macros.rs
 #![feature(if_let_guard)]
-#![allow(clippy::no_effect, unused, clippy::single_match)]
+#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)]
 #![warn(clippy::redundant_guards)]
 
 #[macro_use]
@@ -19,15 +19,24 @@ struct FloatWrapper(f32);
 
 fn issue11304() {
     match 0.1 {
-        x if x == 0.0 => todo!(),
+        0.0 => todo!(),
+        // Pattern matching NAN is illegal
+        x if x == f64::NAN => todo!(),
         _ => todo!(),
     }
     match FloatWrapper(0.1) {
-        x if x == FloatWrapper(0.0) => todo!(),
+        FloatWrapper(0.0) => todo!(),
         _ => todo!(),
     }
 }
 
+fn issue13681() {
+    match c"hi" {
+        x if x == c"hi" => (),
+        _ => (),
+    }
+}
+
 fn main() {
     let c = C(1, 2);
     match c {
diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs
index adbc4ed16cd..b4d4ef5b170 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.rs
+++ b/src/tools/clippy/tests/ui/redundant_guards.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macros.rs
 #![feature(if_let_guard)]
-#![allow(clippy::no_effect, unused, clippy::single_match)]
+#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)]
 #![warn(clippy::redundant_guards)]
 
 #[macro_use]
@@ -20,6 +20,8 @@ struct FloatWrapper(f32);
 fn issue11304() {
     match 0.1 {
         x if x == 0.0 => todo!(),
+        // Pattern matching NAN is illegal
+        x if x == f64::NAN => todo!(),
         _ => todo!(),
     }
     match FloatWrapper(0.1) {
@@ -28,6 +30,13 @@ fn issue11304() {
     }
 }
 
+fn issue13681() {
+    match c"hi" {
+        x if x == c"hi" => (),
+        _ => (),
+    }
+}
+
 fn main() {
     let c = C(1, 2);
     match c {
diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr
index fd12e083282..7512546450b 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.stderr
+++ b/src/tools/clippy/tests/ui/redundant_guards.stderr
@@ -1,19 +1,43 @@
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:34:20
+  --> tests/ui/redundant_guards.rs:22:14
    |
-LL |         C(x, y) if let 1 = y => ..,
-   |                    ^^^^^^^^^
+LL |         x if x == 0.0 => todo!(),
+   |              ^^^^^^^^
    |
    = note: `-D clippy::redundant-guards` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::redundant_guards)]`
 help: try
    |
+LL -         x if x == 0.0 => todo!(),
+LL +         0.0 => todo!(),
+   |
+
+error: redundant guard
+  --> tests/ui/redundant_guards.rs:28:14
+   |
+LL |         x if x == FloatWrapper(0.0) => todo!(),
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL -         x if x == FloatWrapper(0.0) => todo!(),
+LL +         FloatWrapper(0.0) => todo!(),
+   |
+
+error: redundant guard
+  --> tests/ui/redundant_guards.rs:43:20
+   |
+LL |         C(x, y) if let 1 = y => ..,
+   |                    ^^^^^^^^^
+   |
+help: try
+   |
 LL -         C(x, y) if let 1 = y => ..,
 LL +         C(x, 1) => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:40:20
+  --> tests/ui/redundant_guards.rs:49:20
    |
 LL |         Some(x) if matches!(x, Some(1) if true) => ..,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +48,7 @@ LL |         Some(Some(1)) if true => ..,
    |              ~~~~~~~  ~~~~~~~
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:41:20
+  --> tests/ui/redundant_guards.rs:50:20
    |
 LL |         Some(x) if matches!(x, Some(1)) => {
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +60,7 @@ LL +         Some(Some(1)) => {
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:45:20
+  --> tests/ui/redundant_guards.rs:54:20
    |
 LL |         Some(x) if let Some(1) = x => ..,
    |                    ^^^^^^^^^^^^^^^
@@ -48,7 +72,7 @@ LL +         Some(Some(1)) => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:46:20
+  --> tests/ui/redundant_guards.rs:55:20
    |
 LL |         Some(x) if x == Some(2) => ..,
    |                    ^^^^^^^^^^^^
@@ -60,7 +84,7 @@ LL +         Some(Some(2)) => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:47:20
+  --> tests/ui/redundant_guards.rs:56:20
    |
 LL |         Some(x) if Some(2) == x => ..,
    |                    ^^^^^^^^^^^^
@@ -72,7 +96,7 @@ LL +         Some(Some(2)) => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:72:20
+  --> tests/ui/redundant_guards.rs:81:20
    |
 LL |         B { e } if matches!(e, Some(A(2))) => ..,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,7 +108,7 @@ LL +         B { e: Some(A(2)) } => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:109:20
+  --> tests/ui/redundant_guards.rs:118:20
    |
 LL |         E::A(y) if y == "not from an or pattern" => {},
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +120,7 @@ LL +         E::A("not from an or pattern") => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:116:14
+  --> tests/ui/redundant_guards.rs:125:14
    |
 LL |         x if matches!(x, Some(0)) => ..,
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -108,7 +132,7 @@ LL +         Some(0) => ..,
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:123:14
+  --> tests/ui/redundant_guards.rs:132:14
    |
 LL |         i if i == -1 => {},
    |              ^^^^^^^
@@ -120,7 +144,7 @@ LL +         -1 => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:124:14
+  --> tests/ui/redundant_guards.rs:133:14
    |
 LL |         i if i == 1 => {},
    |              ^^^^^^
@@ -132,7 +156,7 @@ LL +         1 => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:186:28
+  --> tests/ui/redundant_guards.rs:195:28
    |
 LL |             Some(ref x) if x == &1 => {},
    |                            ^^^^^^^
@@ -144,7 +168,7 @@ LL +             Some(1) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:187:28
+  --> tests/ui/redundant_guards.rs:196:28
    |
 LL |             Some(ref x) if &1 == x => {},
    |                            ^^^^^^^
@@ -156,7 +180,7 @@ LL +             Some(1) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:188:28
+  --> tests/ui/redundant_guards.rs:197:28
    |
 LL |             Some(ref x) if let &2 = x => {},
    |                            ^^^^^^^^^^
@@ -168,7 +192,7 @@ LL +             Some(2) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:189:28
+  --> tests/ui/redundant_guards.rs:198:28
    |
 LL |             Some(ref x) if matches!(x, &3) => {},
    |                            ^^^^^^^^^^^^^^^
@@ -180,7 +204,7 @@ LL +             Some(3) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:209:32
+  --> tests/ui/redundant_guards.rs:218:32
    |
 LL |             B { ref c, .. } if c == &1 => {},
    |                                ^^^^^^^
@@ -192,7 +216,7 @@ LL +             B { c: 1, .. } => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:210:32
+  --> tests/ui/redundant_guards.rs:219:32
    |
 LL |             B { ref c, .. } if &1 == c => {},
    |                                ^^^^^^^
@@ -204,7 +228,7 @@ LL +             B { c: 1, .. } => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:211:32
+  --> tests/ui/redundant_guards.rs:220:32
    |
 LL |             B { ref c, .. } if let &1 = c => {},
    |                                ^^^^^^^^^^
@@ -216,7 +240,7 @@ LL +             B { c: 1, .. } => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:212:32
+  --> tests/ui/redundant_guards.rs:221:32
    |
 LL |             B { ref c, .. } if matches!(c, &1) => {},
    |                                ^^^^^^^^^^^^^^^
@@ -228,7 +252,7 @@ LL +             B { c: 1, .. } => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:222:26
+  --> tests/ui/redundant_guards.rs:231:26
    |
 LL |         Some(Some(x)) if x.is_empty() => {},
    |                          ^^^^^^^^^^^^
@@ -240,7 +264,7 @@ LL +         Some(Some("")) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:233:26
+  --> tests/ui/redundant_guards.rs:242:26
    |
 LL |         Some(Some(x)) if x.is_empty() => {},
    |                          ^^^^^^^^^^^^
@@ -252,7 +276,7 @@ LL +         Some(Some([])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:238:26
+  --> tests/ui/redundant_guards.rs:247:26
    |
 LL |         Some(Some(x)) if x.is_empty() => {},
    |                          ^^^^^^^^^^^^
@@ -264,7 +288,7 @@ LL +         Some(Some([])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:249:26
+  --> tests/ui/redundant_guards.rs:258:26
    |
 LL |         Some(Some(x)) if x.starts_with(&[]) => {},
    |                          ^^^^^^^^^^^^^^^^^^
@@ -276,7 +300,7 @@ LL +         Some(Some([..])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:254:26
+  --> tests/ui/redundant_guards.rs:263:26
    |
 LL |         Some(Some(x)) if x.starts_with(&[1]) => {},
    |                          ^^^^^^^^^^^^^^^^^^^
@@ -288,7 +312,7 @@ LL +         Some(Some([1, ..])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:259:26
+  --> tests/ui/redundant_guards.rs:268:26
    |
 LL |         Some(Some(x)) if x.starts_with(&[1, 2]) => {},
    |                          ^^^^^^^^^^^^^^^^^^^^^^
@@ -300,7 +324,7 @@ LL +         Some(Some([1, 2, ..])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:264:26
+  --> tests/ui/redundant_guards.rs:273:26
    |
 LL |         Some(Some(x)) if x.ends_with(&[1, 2]) => {},
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -312,7 +336,7 @@ LL +         Some(Some([.., 1, 2])) => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:286:18
+  --> tests/ui/redundant_guards.rs:295:18
    |
 LL |             y if y.is_empty() => {},
    |                  ^^^^^^^^^^^^
@@ -324,7 +348,7 @@ LL +             "" => {},
    |
 
 error: redundant guard
-  --> tests/ui/redundant_guards.rs:305:22
+  --> tests/ui/redundant_guards.rs:314:22
    |
 LL |                 y if y.is_empty() => {},
    |                      ^^^^^^^^^^^^
@@ -335,5 +359,5 @@ LL -                 y if y.is_empty() => {},
 LL +                 "" => {},
    |
 
-error: aborting due to 28 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 0d6e07aa546..47149622ef7 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -59,6 +59,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
@@ -74,6 +75,7 @@
 #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
 #![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
 #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 2ac59718786..7a78a5d280d 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -59,6 +59,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
@@ -74,6 +75,7 @@
 #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
 #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
 #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index a5ae727b7ee..dc24bc16d0e 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> tests/ui/rename.rs:63:9
+  --> tests/ui/rename.rs:64:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> tests/ui/rename.rs:64:9
+  --> tests/ui/rename.rs:65:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:65:9
+  --> tests/ui/rename.rs:66:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:66:9
+  --> tests/ui/rename.rs:67:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:67:9
+  --> tests/ui/rename.rs:68:9
    |
 LL | #![warn(clippy::blocks_in_if_conditions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> tests/ui/rename.rs:68:9
+  --> tests/ui/rename.rs:69:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> tests/ui/rename.rs:69:9
+  --> tests/ui/rename.rs:70:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> tests/ui/rename.rs:70:9
+  --> tests/ui/rename.rs:71:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> tests/ui/rename.rs:71:9
+  --> tests/ui/rename.rs:72:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> tests/ui/rename.rs:72:9
+  --> tests/ui/rename.rs:73:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> tests/ui/rename.rs:73:9
+  --> tests/ui/rename.rs:74:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> tests/ui/rename.rs:74:9
+  --> tests/ui/rename.rs:75:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
-  --> tests/ui/rename.rs:75:9
+  --> tests/ui/rename.rs:76:9
    |
 LL | #![warn(clippy::find_map)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
 
 error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
-  --> tests/ui/rename.rs:76:9
+  --> tests/ui/rename.rs:77:9
    |
 LL | #![warn(clippy::filter_map)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
 
+error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
+  --> tests/ui/rename.rs:78:9
+   |
+LL | #![warn(clippy::fn_address_comparisons)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
+
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> tests/ui/rename.rs:77:9
+  --> tests/ui/rename.rs:79:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
-  --> tests/ui/rename.rs:78:9
+  --> tests/ui/rename.rs:80:9
    |
 LL | #![warn(clippy::if_let_redundant_pattern_matching)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> tests/ui/rename.rs:79:9
+  --> tests/ui/rename.rs:81:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> tests/ui/rename.rs:80:9
+  --> tests/ui/rename.rs:82:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> tests/ui/rename.rs:81:9
+  --> tests/ui/rename.rs:83:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> tests/ui/rename.rs:82:9
+  --> tests/ui/rename.rs:84:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> tests/ui/rename.rs:83:9
+  --> tests/ui/rename.rs:85:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> tests/ui/rename.rs:84:9
+  --> tests/ui/rename.rs:86:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> tests/ui/rename.rs:85:9
+  --> tests/ui/rename.rs:87:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:86:9
+  --> tests/ui/rename.rs:88:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:87:9
+  --> tests/ui/rename.rs:89:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:88:9
+  --> tests/ui/rename.rs:90:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:89:9
+  --> tests/ui/rename.rs:91:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
-  --> tests/ui/rename.rs:90:9
+  --> tests/ui/rename.rs:92:9
    |
 LL | #![warn(clippy::overflow_check_conditional)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> tests/ui/rename.rs:91:9
+  --> tests/ui/rename.rs:93:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:92:9
+  --> tests/ui/rename.rs:94:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:93:9
+  --> tests/ui/rename.rs:95:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:94:9
+  --> tests/ui/rename.rs:96:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> tests/ui/rename.rs:95:9
+  --> tests/ui/rename.rs:97:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> tests/ui/rename.rs:96:9
+  --> tests/ui/rename.rs:98:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
-  --> tests/ui/rename.rs:97:9
+  --> tests/ui/rename.rs:99:9
    |
 LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> tests/ui/rename.rs:98:9
+  --> tests/ui/rename.rs:100:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> tests/ui/rename.rs:99:9
+  --> tests/ui/rename.rs:101:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> tests/ui/rename.rs:100:9
+  --> tests/ui/rename.rs:102:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> tests/ui/rename.rs:101:9
+  --> tests/ui/rename.rs:103:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> tests/ui/rename.rs:102:9
+  --> tests/ui/rename.rs:104:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> tests/ui/rename.rs:103:9
+  --> tests/ui/rename.rs:105:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> tests/ui/rename.rs:104:9
+  --> tests/ui/rename.rs:106:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> tests/ui/rename.rs:105:9
+  --> tests/ui/rename.rs:107:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> tests/ui/rename.rs:106:9
+  --> tests/ui/rename.rs:108:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> tests/ui/rename.rs:107:9
+  --> tests/ui/rename.rs:109:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:108:9
+  --> tests/ui/rename.rs:110:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:109:9
+  --> tests/ui/rename.rs:111:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:110:9
+  --> tests/ui/rename.rs:112:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> tests/ui/rename.rs:111:9
+  --> tests/ui/rename.rs:113:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> tests/ui/rename.rs:112:9
+  --> tests/ui/rename.rs:114:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> tests/ui/rename.rs:113:9
+  --> tests/ui/rename.rs:115:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> tests/ui/rename.rs:114:9
+  --> tests/ui/rename.rs:116:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> tests/ui/rename.rs:115:9
+  --> tests/ui/rename.rs:117:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> tests/ui/rename.rs:116:9
+  --> tests/ui/rename.rs:118:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> tests/ui/rename.rs:117:9
+  --> tests/ui/rename.rs:119:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:118:9
+  --> tests/ui/rename.rs:120:9
    |
 LL | #![warn(clippy::maybe_misused_cfg)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> tests/ui/rename.rs:119:9
+  --> tests/ui/rename.rs:121:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:120:9
+  --> tests/ui/rename.rs:122:9
    |
 LL | #![warn(clippy::mismatched_target_os)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> tests/ui/rename.rs:121:9
+  --> tests/ui/rename.rs:123:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> tests/ui/rename.rs:122:9
+  --> tests/ui/rename.rs:124:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
-  --> tests/ui/rename.rs:123:9
+  --> tests/ui/rename.rs:125:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> tests/ui/rename.rs:124:9
+  --> tests/ui/rename.rs:126:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> tests/ui/rename.rs:125:9
+  --> tests/ui/rename.rs:127:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> tests/ui/rename.rs:126:9
+  --> tests/ui/rename.rs:128:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
 error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
-  --> tests/ui/rename.rs:127:9
+  --> tests/ui/rename.rs:129:9
    |
 LL | #![warn(clippy::vtable_address_comparisons)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
 
 error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
-  --> tests/ui/rename.rs:128:9
+  --> tests/ui/rename.rs:130:9
    |
 LL | #![warn(clippy::reverse_range_loop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
 
-error: aborting due to 66 previous errors
+error: aborting due to 67 previous errors
 
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index 779431303ae..708512793d5 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -1,6 +1,6 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
-#![feature(const_trait_impl)]
+#![feature(associated_const_equality, const_trait_impl)]
 
 use std::any::Any;
 
@@ -179,3 +179,19 @@ fn main() {
     let _x: fn(_) = f::<()>;
     let _x: fn(_) = f::<i32>;
 }
+
+// #13706
+fn assoc_tys_bounds<T>()
+where
+    T: Iterator<Item: Clone> + Iterator<Item: Clone>,
+{
+}
+trait AssocConstTrait {
+    const ASSOC: usize;
+}
+fn assoc_const_args<T>()
+where
+    T: AssocConstTrait<ASSOC = 0>,
+    //~^ trait_duplication_in_bounds
+{
+}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index 3e974dc0a8f..12db6b65a7a 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -1,6 +1,6 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
-#![feature(const_trait_impl)]
+#![feature(associated_const_equality, const_trait_impl)]
 
 use std::any::Any;
 
@@ -179,3 +179,19 @@ fn main() {
     let _x: fn(_) = f::<()>;
     let _x: fn(_) = f::<i32>;
 }
+
+// #13706
+fn assoc_tys_bounds<T>()
+where
+    T: Iterator<Item: Clone> + Iterator<Item: Clone>,
+{
+}
+trait AssocConstTrait {
+    const ASSOC: usize;
+}
+fn assoc_const_args<T>()
+where
+    T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
+    //~^ trait_duplication_in_bounds
+{
+}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
index 0dd508e4745..83c06eaccd4 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
@@ -70,5 +70,11 @@ error: these where clauses contain repeated elements
 LL |     T: IntoIterator<Item = U::Owned> + IntoIterator<Item = U::Owned>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator<Item = U::Owned>`
 
-error: aborting due to 11 previous errors
+error: these where clauses contain repeated elements
+  --> tests/ui/trait_duplication_in_bounds.rs:194:8
+   |
+LL |     T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait<ASSOC = 0>`
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index 3f5b0e52ece..111a2e1987c 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -257,8 +257,6 @@ fn tester2() {
     my_concat!("{}", local_i32);
     my_good_macro!("{}", local_i32);
     my_good_macro!("{}", local_i32,);
-
-    // FIXME: Broken false positives, currently unhandled
     my_bad_macro!("{}", local_i32);
     my_bad_macro2!("{}", local_i32);
     used_twice! {
@@ -267,3 +265,22 @@ fn tester2() {
         local_i32,
     };
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn user_format() {
+    let local_i32 = 1;
+    let local_f64 = 2.0;
+
+    usr_println!(true, "val='{local_i32}'");
+    usr_println!(true, "{local_i32}");
+    usr_println!(true, "{local_i32:#010x}");
+    usr_println!(true, "{local_f64:.1}");
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index b311aa4912c..81fe2476567 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -262,8 +262,6 @@ fn tester2() {
     my_concat!("{}", local_i32);
     my_good_macro!("{}", local_i32);
     my_good_macro!("{}", local_i32,);
-
-    // FIXME: Broken false positives, currently unhandled
     my_bad_macro!("{}", local_i32);
     my_bad_macro2!("{}", local_i32);
     used_twice! {
@@ -272,3 +270,22 @@ fn tester2() {
         local_i32,
     };
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn user_format() {
+    let local_i32 = 1;
+    let local_f64 = 2.0;
+
+    usr_println!(true, "val='{}'", local_i32);
+    usr_println!(true, "{}", local_i32);
+    usr_println!(true, "{:#010x}", local_i32);
+    usr_println!(true, "{:.1}", local_f64);
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.stderr b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
index 5a7ff3bc4f5..77961fea2c5 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.stderr
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
@@ -845,5 +845,53 @@ LL -     println!("expand='{}'", local_i32);
 LL +     println!("expand='{local_i32}'");
    |
 
-error: aborting due to 71 previous errors
+error: variables can be used directly in the `format!` string
+  --> tests/ui/uninlined_format_args.rs:287:5
+   |
+LL |     usr_println!(true, "val='{}'", local_i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     usr_println!(true, "val='{}'", local_i32);
+LL +     usr_println!(true, "val='{local_i32}'");
+   |
+
+error: variables can be used directly in the `format!` string
+  --> tests/ui/uninlined_format_args.rs:288:5
+   |
+LL |     usr_println!(true, "{}", local_i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     usr_println!(true, "{}", local_i32);
+LL +     usr_println!(true, "{local_i32}");
+   |
+
+error: variables can be used directly in the `format!` string
+  --> tests/ui/uninlined_format_args.rs:289:5
+   |
+LL |     usr_println!(true, "{:#010x}", local_i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     usr_println!(true, "{:#010x}", local_i32);
+LL +     usr_println!(true, "{local_i32:#010x}");
+   |
+
+error: variables can be used directly in the `format!` string
+  --> tests/ui/uninlined_format_args.rs:290:5
+   |
+LL |     usr_println!(true, "{:.1}", local_f64);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     usr_println!(true, "{:.1}", local_f64);
+LL +     usr_println!(true, "{local_f64:.1}");
+   |
+
+error: aborting due to 75 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 2d932a70e9d..70b78ceca50 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
@@ -23,10 +23,9 @@ fn main() {
     let _ = Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5]);
     let _ = (Ok::<i32, i32>(5) == Ok(5));
     let _ = (Some(5) == Some(5)).then(|| 1);
+    let _ = Some(5).is_none_or(|n| n == 5);
+    let _ = Some(5).is_none_or(|n| 5 == n);
 
-    // shouldnt trigger
-    let _ = Some(5).map_or(true, |n| n == 5);
-    let _ = Some(5).map_or(true, |n| 5 == n);
     macro_rules! x {
         () => {
             Some(1)
@@ -51,10 +50,21 @@ fn main() {
     let r: Result<i32, S> = Ok(3);
     let _ = r.is_ok_and(|x| x == 7);
 
+    // lint constructs that are not comparaisons as well
+    let func = |_x| true;
+    let r: Result<i32, S> = Ok(3);
+    let _ = r.is_ok_and(func);
+    let _ = Some(5).is_some_and(func);
+    let _ = Some(5).is_none_or(func);
+
     #[derive(PartialEq)]
     struct S2;
     let r: Result<i32, S2> = Ok(4);
     let _ = (r == Ok(8));
+
+    // do not lint `Result::map_or(true, …)`
+    let r: Result<i32, S2> = Ok(4);
+    let _ = r.map_or(true, |x| x == 8);
 }
 
 #[clippy::msrv = "1.69.0"]
@@ -62,3 +72,9 @@ fn msrv_1_69() {
     // is_some_and added in 1.70.0
     let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
 }
+
+#[clippy::msrv = "1.81.0"]
+fn msrv_1_81() {
+    // is_none_or added in 1.82.0
+    let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
index 4a9d69be1e9..50757715977 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
@@ -26,10 +26,9 @@ fn main() {
     let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
     let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
     let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
-
-    // shouldnt trigger
     let _ = Some(5).map_or(true, |n| n == 5);
     let _ = Some(5).map_or(true, |n| 5 == n);
+
     macro_rules! x {
         () => {
             Some(1)
@@ -54,10 +53,21 @@ fn main() {
     let r: Result<i32, S> = Ok(3);
     let _ = r.map_or(false, |x| x == 7);
 
+    // lint constructs that are not comparaisons as well
+    let func = |_x| true;
+    let r: Result<i32, S> = Ok(3);
+    let _ = r.map_or(false, func);
+    let _ = Some(5).map_or(false, func);
+    let _ = Some(5).map_or(true, func);
+
     #[derive(PartialEq)]
     struct S2;
     let r: Result<i32, S2> = Ok(4);
     let _ = r.map_or(false, |x| x == 8);
+
+    // do not lint `Result::map_or(true, …)`
+    let r: Result<i32, S2> = Ok(4);
+    let _ = r.map_or(true, |x| x == 8);
 }
 
 #[clippy::msrv = "1.69.0"]
@@ -65,3 +75,9 @@ fn msrv_1_69() {
     // is_some_and added in 1.70.0
     let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
 }
+
+#[clippy::msrv = "1.81.0"]
+fn msrv_1_81() {
+    // is_none_or added in 1.82.0
+    let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
index 299a4e5da7a..890abb01228 100644
--- a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
@@ -1,4 +1,4 @@
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:12:13
    |
 LL |     let _ = Some(5).map_or(false, |n| n == 5);
@@ -7,13 +7,13 @@ LL |     let _ = Some(5).map_or(false, |n| n == 5);
    = note: `-D clippy::unnecessary-map-or` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:13:13
    |
 LL |     let _ = Some(5).map_or(true, |n| n != 5);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:14:13
    |
 LL |       let _ = Some(5).map_or(false, |n| {
@@ -23,7 +23,7 @@ LL | |         n == 5
 LL | |     });
    | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:18:13
    |
 LL |       let _ = Some(5).map_or(false, |n| {
@@ -41,59 +41,89 @@ LL +         6 >= 5
 LL ~     });
    |
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:22:13
    |
 LL |     let _ = Some(vec![5]).map_or(false, |n| n == [5]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:23:13
    |
 LL |     let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:24:13
    |
 LL |     let _ = Some(5).map_or(false, |n| n == n);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:25:13
    |
 LL |     let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:26:13
    |
 LL |     let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5])`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:27:13
    |
 LL |     let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::<i32, i32>(5) == Ok(5))`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:28:13
    |
 LL |     let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))`
 
-error: this `map_or` is redundant
-  --> tests/ui/unnecessary_map_or.rs:55:13
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:29:13
+   |
+LL |     let _ = Some(5).map_or(true, |n| n == 5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| n == 5)`
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:30:13
+   |
+LL |     let _ = Some(5).map_or(true, |n| 5 == n);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| 5 == n)`
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:54:13
    |
 LL |     let _ = r.map_or(false, |x| x == 7);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)`
 
-error: this `map_or` is redundant
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:59:13
+   |
+LL |     let _ = r.map_or(false, func);
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(func)`
+
+error: this `map_or` can be simplified
   --> tests/ui/unnecessary_map_or.rs:60:13
    |
+LL |     let _ = Some(5).map_or(false, func);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(func)`
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:61:13
+   |
+LL |     let _ = Some(5).map_or(true, func);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(func)`
+
+error: this `map_or` can be simplified
+  --> tests/ui/unnecessary_map_or.rs:66:13
+   |
 LL |     let _ = r.map_or(false, |x| x == 8);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))`
 
-error: aborting due to 13 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.1.fixed b/src/tools/clippy/tests/ui/unused_format_specs.1.fixed
index b7d1cce2870..157c2b08d3c 100644
--- a/src/tools/clippy/tests/ui/unused_format_specs.1.fixed
+++ b/src/tools/clippy/tests/ui/unused_format_specs.1.fixed
@@ -33,3 +33,38 @@ fn should_not_lint() {
     let args = format_args!("");
     println!("{args}");
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn should_lint_user() {
+    // prints `.`, not `     .`
+    usr_println!(true, "{:5}.", format!(""));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+    //prints `abcde`, not `abc`
+    usr_println!(true, "{:.3}", format!("abcde"));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    usr_println!(true, "{}.", format_args_from_macro!());
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    let args = format_args!("");
+    usr_println!(true, "{args}");
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+}
+
+fn should_not_lint_user() {
+    usr_println!(true, "{}", format_args!(""));
+    // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
+    // debug formatting so allow it
+    usr_println!(true, "{:?}", format_args!(""));
+
+    let args = format_args!("");
+    usr_println!(true, "{args}");
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.2.fixed b/src/tools/clippy/tests/ui/unused_format_specs.2.fixed
index 94bb6b7036b..92c7b951f3c 100644
--- a/src/tools/clippy/tests/ui/unused_format_specs.2.fixed
+++ b/src/tools/clippy/tests/ui/unused_format_specs.2.fixed
@@ -33,3 +33,38 @@ fn should_not_lint() {
     let args = format_args!("");
     println!("{args}");
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn should_lint_user() {
+    // prints `.`, not `     .`
+    usr_println!(true, "{}.", format_args!(""));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+    //prints `abcde`, not `abc`
+    usr_println!(true, "{}", format_args!("abcde"));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    usr_println!(true, "{}.", format_args_from_macro!());
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    let args = format_args!("");
+    usr_println!(true, "{args}");
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+}
+
+fn should_not_lint_user() {
+    usr_println!(true, "{}", format_args!(""));
+    // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
+    // debug formatting so allow it
+    usr_println!(true, "{:?}", format_args!(""));
+
+    let args = format_args!("");
+    usr_println!(true, "{args}");
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.rs b/src/tools/clippy/tests/ui/unused_format_specs.rs
index 2c85e371149..a5df4d8a866 100644
--- a/src/tools/clippy/tests/ui/unused_format_specs.rs
+++ b/src/tools/clippy/tests/ui/unused_format_specs.rs
@@ -33,3 +33,38 @@ fn should_not_lint() {
     let args = format_args!("");
     println!("{args}");
 }
+
+#[clippy::format_args]
+macro_rules! usr_println {
+    ($target:expr, $($args:tt)*) => {{
+        if $target {
+            println!($($args)*)
+        }
+    }};
+}
+
+fn should_lint_user() {
+    // prints `.`, not `     .`
+    usr_println!(true, "{:5}.", format_args!(""));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+    //prints `abcde`, not `abc`
+    usr_println!(true, "{:.3}", format_args!("abcde"));
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    usr_println!(true, "{:5}.", format_args_from_macro!());
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+
+    let args = format_args!("");
+    usr_println!(true, "{args:5}");
+    //~^ ERROR: format specifiers have no effect on `format_args!()`
+}
+
+fn should_not_lint_user() {
+    usr_println!(true, "{}", format_args!(""));
+    // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
+    // debug formatting so allow it
+    usr_println!(true, "{:?}", format_args!(""));
+
+    let args = format_args!("");
+    usr_println!(true, "{args}");
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.stderr b/src/tools/clippy/tests/ui/unused_format_specs.stderr
index 2b5c81c63d6..df61d59130e 100644
--- a/src/tools/clippy/tests/ui/unused_format_specs.stderr
+++ b/src/tools/clippy/tests/ui/unused_format_specs.stderr
@@ -58,5 +58,63 @@ LL -     println!("{args:5}");
 LL +     println!("{args}");
    |
 
-error: aborting due to 4 previous errors
+error: format specifiers have no effect on `format_args!()`
+  --> tests/ui/unused_format_specs.rs:48:25
+   |
+LL |     usr_println!(true, "{:5}.", format_args!(""));
+   |                         ^^^^
+   |
+help: for the width to apply consider using `format!()`
+   |
+LL |     usr_println!(true, "{:5}.", format!(""));
+   |                                 ~~~~~~
+help: if the current behavior is intentional, remove the format specifiers
+   |
+LL -     usr_println!(true, "{:5}.", format_args!(""));
+LL +     usr_println!(true, "{}.", format_args!(""));
+   |
+
+error: format specifiers have no effect on `format_args!()`
+  --> tests/ui/unused_format_specs.rs:51:25
+   |
+LL |     usr_println!(true, "{:.3}", format_args!("abcde"));
+   |                         ^^^^^
+   |
+help: for the precision to apply consider using `format!()`
+   |
+LL |     usr_println!(true, "{:.3}", format!("abcde"));
+   |                                 ~~~~~~
+help: if the current behavior is intentional, remove the format specifiers
+   |
+LL -     usr_println!(true, "{:.3}", format_args!("abcde"));
+LL +     usr_println!(true, "{}", format_args!("abcde"));
+   |
+
+error: format specifiers have no effect on `format_args!()`
+  --> tests/ui/unused_format_specs.rs:54:25
+   |
+LL |     usr_println!(true, "{:5}.", format_args_from_macro!());
+   |                         ^^^^
+   |
+   = help: for the width to apply consider using `format!()`
+help: if the current behavior is intentional, remove the format specifiers
+   |
+LL -     usr_println!(true, "{:5}.", format_args_from_macro!());
+LL +     usr_println!(true, "{}.", format_args_from_macro!());
+   |
+
+error: format specifiers have no effect on `format_args!()`
+  --> tests/ui/unused_format_specs.rs:58:25
+   |
+LL |     usr_println!(true, "{args:5}");
+   |                         ^^^^^^^^
+   |
+   = help: for the width to apply consider using `format!()`
+help: if the current behavior is intentional, remove the format specifiers
+   |
+LL -     usr_println!(true, "{args:5}");
+LL +     usr_println!(true, "{args}");
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index e6fbba943a4..36f876bcdc6 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -1,4 +1,4 @@
-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeSet, HashMap, HashSet};
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::Command;
@@ -486,6 +486,9 @@ impl Config {
     }
 }
 
+/// Known widths of `target_has_atomic`.
+pub const KNOWN_TARGET_HAS_ATOMIC_WIDTHS: &[&str] = &["8", "16", "32", "64", "128", "ptr"];
+
 #[derive(Debug, Clone)]
 pub struct TargetCfgs {
     pub current: TargetCfg,
@@ -611,6 +614,17 @@ impl TargetCfgs {
                 ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort,
                 ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind,
                 ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"),
+
+                ("target_has_atomic", Some(width))
+                    if KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width) =>
+                {
+                    cfg.target_has_atomic.insert(width.to_string());
+                }
+                ("target_has_atomic", Some(other)) => {
+                    panic!("unexpected value for `target_has_atomic` cfg: {other:?}")
+                }
+                // Nightly-only std-internal impl detail.
+                ("target_has_atomic", None) => {}
                 _ => {}
             }
         }
@@ -645,6 +659,12 @@ pub struct TargetCfg {
     pub(crate) xray: bool,
     #[serde(default = "default_reloc_model")]
     pub(crate) relocation_model: String,
+
+    // Not present in target cfg json output, additional derived information.
+    #[serde(skip)]
+    /// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin
+    /// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`.
+    pub(crate) target_has_atomic: BTreeSet<String>,
 }
 
 impl TargetCfg {
diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs
index 92c80c27de0..3ace6c5b6d7 100644
--- a/src/tools/compiletest/src/compute_diff.rs
+++ b/src/tools/compiletest/src/compute_diff.rs
@@ -144,7 +144,7 @@ where
     }
 
     if !wrote_data {
-        println!("note: diff is identical to nightly rustdoc");
+        eprintln!("note: diff is identical to nightly rustdoc");
         assert!(diff_output.metadata().unwrap().len() == 0);
         return false;
     } else if verbose {
diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs
index b605bc813f1..e75c8a5993e 100644
--- a/src/tools/compiletest/src/debuggers.rs
+++ b/src/tools/compiletest/src/debuggers.rs
@@ -20,7 +20,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.remote_test_client.is_some() && !config.target.contains("android") {
-        println!(
+        eprintln!(
             "WARNING: debuginfo tests are not available when \
              testing with remote"
         );
@@ -28,7 +28,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.target.contains("android") {
-        println!(
+        eprintln!(
             "{} debug-info test uses tcp 5039 port.\
              please reserve it",
             config.target
@@ -50,7 +50,7 @@ pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
     config.lldb_python_dir.as_ref()?;
 
     if let Some(350) = config.lldb_version {
-        println!(
+        eprintln!(
             "WARNING: The used version of LLDB (350) has a \
              known issue that breaks debuginfo tests. See \
              issue #32520 for more information. Skipping all \
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 0c47ef871d2..5638d471890 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -17,7 +17,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-run-results",
     "check-stdout",
     "check-test-line-numbers-match",
-    "compare-output-lines-by-subset",
     "compile-flags",
     "doc-flags",
     "dont-check-compiler-stderr",
@@ -154,6 +153,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-thread",
     "needs-std-debug-assertions",
     "needs-symlink",
+    "needs-target-has-atomic",
     "needs-threads",
     "needs-unwind",
     "needs-wasmtime",
@@ -215,6 +215,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "pp-exact",
     "pretty-compare-only",
     "pretty-mode",
+    "proc-macro",
     "reference",
     "regex-error-pattern",
     "remap-src-base",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index e945797647e..91558d0c898 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -115,9 +115,6 @@ pub struct TestProps {
     pub dont_check_compiler_stdout: bool,
     // For UI tests, allows compiler to generate arbitrary output to stderr
     pub dont_check_compiler_stderr: bool,
-    // When checking the output of stdout or stderr check
-    // that the lines of expected output are a subset of the actual output.
-    pub compare_output_lines_by_subset: bool,
     // Don't force a --crate-type=dylib flag on the command line
     //
     // Set this for example if you have an auxiliary test file that contains
@@ -221,6 +218,7 @@ mod directives {
     pub const AUX_BIN: &'static str = "aux-bin";
     pub const AUX_BUILD: &'static str = "aux-build";
     pub const AUX_CRATE: &'static str = "aux-crate";
+    pub const PROC_MACRO: &'static str = "proc-macro";
     pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend";
     pub const EXEC_ENV: &'static str = "exec-env";
     pub const RUSTC_ENV: &'static str = "rustc-env";
@@ -239,7 +237,6 @@ mod directives {
     pub const KNOWN_BUG: &'static str = "known-bug";
     pub const TEST_MIR_PASS: &'static str = "test-mir-pass";
     pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
-    pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
     pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
     pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
     pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
@@ -273,7 +270,6 @@ impl TestProps {
             check_run_results: false,
             dont_check_compiler_stdout: false,
             dont_check_compiler_stderr: false,
-            compare_output_lines_by_subset: false,
             no_prefer_dynamic: false,
             pretty_mode: "normal".to_string(),
             pretty_compare_only: false,
@@ -549,11 +545,6 @@ impl TestProps {
                         |s| s.trim().to_string(),
                     );
                     config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
-                    config.set_name_directive(
-                        ln,
-                        COMPARE_OUTPUT_LINES_BY_SUBSET,
-                        &mut self.compare_output_lines_by_subset,
-                    );
 
                     if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
                         self.llvm_cov_flags.extend(split_flags(&flags));
@@ -1134,6 +1125,8 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
     .captures(header)?;
     let regex = captures["regex"].to_owned();
     let replacement = captures["replacement"].to_owned();
+    // FIXME: Support escaped new-line in strings.
+    let replacement = replacement.replace("\\n", "\n");
     Some((regex, replacement))
 }
 
diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs
index 6f6538ce196..0e1f3a785f8 100644
--- a/src/tools/compiletest/src/header/auxiliary.rs
+++ b/src/tools/compiletest/src/header/auxiliary.rs
@@ -4,7 +4,7 @@
 use std::iter;
 
 use crate::common::Config;
-use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE};
+use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
 
 /// Properties parsed from `aux-*` test directives.
 #[derive(Clone, Debug, Default)]
@@ -17,6 +17,8 @@ pub(crate) struct AuxProps {
     /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies
     /// to build and pass with the `--extern` flag.
     pub(crate) crates: Vec<(String, String)>,
+    /// Same as `builds`, but for proc-macros.
+    pub(crate) proc_macros: Vec<String>,
     /// Similar to `builds`, but also uses the resulting dylib as a
     /// `-Zcodegen-backend` when compiling the test file.
     pub(crate) codegen_backend: Option<String>,
@@ -26,12 +28,13 @@ impl AuxProps {
     /// Yields all of the paths (relative to `./auxiliary/`) that have been
     /// specified in `aux-*` directives for this test.
     pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> {
-        let Self { builds, bins, crates, codegen_backend } = self;
+        let Self { builds, bins, crates, proc_macros, codegen_backend } = self;
 
         iter::empty()
             .chain(builds.iter().map(String::as_str))
             .chain(bins.iter().map(String::as_str))
             .chain(crates.iter().map(|(_, path)| path.as_str()))
+            .chain(proc_macros.iter().map(String::as_str))
             .chain(codegen_backend.iter().map(String::as_str))
     }
 }
@@ -39,13 +42,15 @@ impl AuxProps {
 /// If the given test directive line contains an `aux-*` directive, parse it
 /// and update [`AuxProps`] accordingly.
 pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) {
-    if !ln.starts_with("aux-") {
+    if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) {
         return;
     }
 
     config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string());
     config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string());
     config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate);
+    config
+        .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string());
     if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
         aux.codegen_backend = Some(r.trim().to_owned());
     }
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 77570c58db5..e19dcd992fc 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -1,4 +1,4 @@
-use crate::common::{Config, Sanitizer};
+use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
 use crate::header::{IgnoreDecision, llvm_has_libzstd};
 
 pub(super) fn handle_needs(
@@ -171,11 +171,54 @@ pub(super) fn handle_needs(
         },
     ];
 
-    let (name, comment) = match ln.split_once([':', ' ']) {
-        Some((name, comment)) => (name, Some(comment)),
+    let (name, rest) = match ln.split_once([':', ' ']) {
+        Some((name, rest)) => (name, Some(rest)),
         None => (ln, None),
     };
 
+    // FIXME(jieyouxu): tighten up this parsing to reject using both `:` and ` ` as means to
+    // delineate value.
+    if name == "needs-target-has-atomic" {
+        let Some(rest) = rest else {
+            return IgnoreDecision::Error {
+                message: "expected `needs-target-has-atomic` to have a comma-separated list of atomic widths".to_string(),
+            };
+        };
+
+        // Expect directive value to be a list of comma-separated atomic widths.
+        let specified_widths = rest
+            .split(',')
+            .map(|width| width.trim())
+            .map(ToString::to_string)
+            .collect::<Vec<String>>();
+
+        for width in &specified_widths {
+            if !KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width.as_str()) {
+                return IgnoreDecision::Error {
+                    message: format!(
+                        "unknown width specified in `needs-target-has-atomic`: `{width}` is not a \
+                        known `target_has_atomic_width`, known values are `{:?}`",
+                        KNOWN_TARGET_HAS_ATOMIC_WIDTHS
+                    ),
+                };
+            }
+        }
+
+        let satisfies_all_specified_widths = specified_widths
+            .iter()
+            .all(|specified| config.target_cfg().target_has_atomic.contains(specified));
+        if satisfies_all_specified_widths {
+            return IgnoreDecision::Continue;
+        } else {
+            return IgnoreDecision::Ignore {
+                reason: format!(
+                    "skipping test as target does not support all of the required `target_has_atomic` widths `{:?}`",
+                    specified_widths
+                ),
+            };
+        }
+    }
+
     if !name.starts_with("needs-") {
         return IgnoreDecision::Continue;
     }
@@ -193,7 +236,7 @@ pub(super) fn handle_needs(
                 break;
             } else {
                 return IgnoreDecision::Ignore {
-                    reason: if let Some(comment) = comment {
+                    reason: if let Some(comment) = rest {
                         format!("{} ({})", need.ignore_reason, comment.trim())
                     } else {
                         need.ignore_reason.into()
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 4d75c38dd32..cd7c6f8361e 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -787,3 +787,40 @@ fn test_not_trailing_directive() {
     run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental");
     assert!(!poisoned);
 }
+
+#[test]
+fn test_needs_target_has_atomic() {
+    use std::collections::BTreeSet;
+
+    // `x86_64-unknown-linux-gnu` supports `["8", "16", "32", "64", "ptr"]` but not `128`.
+
+    let config = cfg().target("x86_64-unknown-linux-gnu").build();
+    // Expectation sanity check.
+    assert_eq!(
+        config.target_cfg().target_has_atomic,
+        BTreeSet::from([
+            "8".to_string(),
+            "16".to_string(),
+            "32".to_string(),
+            "64".to_string(),
+            "ptr".to_string()
+        ]),
+        "expected `x86_64-unknown-linux-gnu` to not have 128-bit atomic support"
+    );
+
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 16"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 32"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 64"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: ptr"));
+
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 128"));
+
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr"));
+
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr,128"));
+
+    // Check whitespace between widths is permitted.
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr"));
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128"));
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index bf4a3124075..9acb7d393b4 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -37,8 +37,8 @@ use walkdir::WalkDir;
 
 use self::header::{EarlyProps, make_test_description};
 use crate::common::{
-    Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir,
-    output_relative_path,
+    CompareMode, Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path,
+    output_base_dir, output_relative_path,
 };
 use crate::header::HeadersCache;
 use crate::util::logv;
@@ -188,8 +188,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
     let (argv0, args_) = args.split_first().unwrap();
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
+        eprintln!("{}", opts.usage(&message));
+        eprintln!();
         panic!()
     }
 
@@ -200,8 +200,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
+        eprintln!("{}", opts.usage(&message));
+        eprintln!();
         panic!()
     }
 
@@ -273,6 +273,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
     } else {
         matches.free.clone()
     };
+    let compare_mode = matches.opt_str("compare-mode").map(|s| {
+        s.parse().unwrap_or_else(|_| {
+            let variants: Vec<_> = CompareMode::STR_VARIANTS.iter().copied().collect();
+            panic!(
+                "`{s}` is not a valid value for `--compare-mode`, it should be one of: {}",
+                variants.join(", ")
+            );
+        })
+    });
     Config {
         bless: matches.opt_present("bless"),
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
@@ -342,9 +351,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         only_modified: matches.opt_present("only-modified"),
         color,
         remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
-        compare_mode: matches
-            .opt_str("compare-mode")
-            .map(|s| s.parse().expect("invalid --compare-mode provided")),
+        compare_mode,
         rustfix_coverage: matches.opt_present("rustfix-coverage"),
         has_html_tidy,
         has_enzyme,
@@ -501,7 +508,7 @@ pub fn run_tests(config: Arc<Config>) {
             // easy to miss which tests failed, and as such fail to reproduce
             // the failure locally.
 
-            println!(
+            eprintln!(
                 "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
                 config.suite,
                 config
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index bc80c8246ad..ca746ed8c55 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -22,7 +22,7 @@ use crate::common::{
     UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir,
     output_base_dir, output_base_name, output_testname_unique,
 };
-use crate::compute_diff::{write_diff, write_filtered_diff};
+use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
 use crate::read2::{Truncated, read2_abbreviated};
@@ -102,7 +102,7 @@ fn get_lib_name(name: &str, aux_type: AuxType) -> Option<String> {
         // In this case, the only path we can pass
         // with '--extern-meta' is the '.rlib' file
         AuxType::Lib => Some(format!("lib{name}.rlib")),
-        AuxType::Dylib => Some(dylib_name(name)),
+        AuxType::Dylib | AuxType::ProcMacro => Some(dylib_name(name)),
     }
 }
 
@@ -131,7 +131,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
 
     if config.verbose {
         // We're going to be dumping a lot of info. Start on a new line.
-        print!("\n\n");
+        eprintln!("\n");
     }
     debug!("running {:?}", testpaths.file.display());
     let mut props = TestProps::from_file(&testpaths.file, revision, &config);
@@ -350,10 +350,13 @@ impl<'test> TestCx<'test> {
             }
         } else {
             if proc_res.status.success() {
-                self.fatal_proc_rec(
-                    &format!("{} test compiled successfully!", self.config.mode)[..],
-                    proc_res,
-                );
+                {
+                    self.error(&format!("{} test did not emit an error", self.config.mode));
+                    if self.config.mode == crate::common::Mode::Ui {
+                        eprintln!("note: by default, ui tests are expected not to compile");
+                    }
+                    proc_res.fatal(None, || ());
+                };
             }
 
             if !self.props.dont_check_failure_status {
@@ -771,20 +774,20 @@ impl<'test> TestCx<'test> {
                 unexpected.len(),
                 not_found.len()
             ));
-            println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
+            eprintln!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
             if !unexpected.is_empty() {
-                println!("{}", "--- unexpected errors (from JSON output) ---".green());
+                eprintln!("{}", "--- unexpected errors (from JSON output) ---".green());
                 for error in &unexpected {
-                    println!("{}", error.render_for_expected());
+                    eprintln!("{}", error.render_for_expected());
                 }
-                println!("{}", "---".green());
+                eprintln!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                println!("{}", "--- not found errors (from test file) ---".red());
+                eprintln!("{}", "--- not found errors (from test file) ---".red());
                 for error in &not_found {
-                    println!("{}", error.render_for_expected());
+                    eprintln!("{}", error.render_for_expected());
                 }
-                println!("{}", "---\n".red());
+                eprintln!("{}", "---\n".red());
             }
             panic!("errors differ from expected");
         }
@@ -1097,7 +1100,9 @@ impl<'test> TestCx<'test> {
     }
 
     fn has_aux_dir(&self) -> bool {
-        !self.props.aux.builds.is_empty() || !self.props.aux.crates.is_empty()
+        !self.props.aux.builds.is_empty()
+            || !self.props.aux.crates.is_empty()
+            || !self.props.aux.proc_macros.is_empty()
     }
 
     fn aux_output_dir(&self) -> PathBuf {
@@ -1118,31 +1123,48 @@ impl<'test> TestCx<'test> {
 
     fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
         for rel_ab in &self.props.aux.builds {
-            self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
+            self.build_auxiliary(of, rel_ab, &aux_dir, None);
         }
 
         for rel_ab in &self.props.aux.bins {
-            self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
+            self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin));
         }
 
+        let path_to_crate_name = |path: &str| -> String {
+            path.rsplit_once('/')
+                .map_or(path, |(_, tail)| tail)
+                .trim_end_matches(".rs")
+                .replace('-', "_")
+        };
+
+        let add_extern =
+            |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| {
+                let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
+                if let Some(lib_name) = lib_name {
+                    rustc.arg("--extern").arg(format!(
+                        "{}={}/{}",
+                        aux_name,
+                        aux_dir.display(),
+                        lib_name
+                    ));
+                }
+            };
+
         for (aux_name, aux_path) in &self.props.aux.crates {
-            let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
-            let lib_name =
-                get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
-            if let Some(lib_name) = lib_name {
-                rustc.arg("--extern").arg(format!(
-                    "{}={}/{}",
-                    aux_name,
-                    aux_dir.display(),
-                    lib_name
-                ));
-            }
+            let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None);
+            add_extern(rustc, aux_name, aux_path, aux_type);
+        }
+
+        for proc_macro in &self.props.aux.proc_macros {
+            self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro));
+            let crate_name = path_to_crate_name(proc_macro);
+            add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro);
         }
 
         // Build any `//@ aux-codegen-backend`, and pass the resulting library
         // to `-Zcodegen-backend` when compiling the test file.
         if let Some(aux_file) = &self.props.aux.codegen_backend {
-            let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false);
+            let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None);
             if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
                 let lib_path = aux_dir.join(&lib_name);
                 rustc.arg(format!("-Zcodegen-backend={}", lib_path.display()));
@@ -1209,17 +1231,23 @@ impl<'test> TestCx<'test> {
     }
 
     /// Builds an aux dependency.
+    ///
+    /// If `aux_type` is `None`, then this will determine the aux-type automatically.
     fn build_auxiliary(
         &self,
         of: &TestPaths,
         source_path: &str,
         aux_dir: &Path,
-        is_bin: bool,
+        aux_type: Option<AuxType>,
     ) -> AuxType {
         let aux_testpaths = self.compute_aux_test_paths(of, source_path);
-        let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
+        let mut aux_props =
+            self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
+        if aux_type == Some(AuxType::ProcMacro) {
+            aux_props.force_host = true;
+        }
         let mut aux_dir = aux_dir.to_path_buf();
-        if is_bin {
+        if aux_type == Some(AuxType::Bin) {
             // On unix, the binary of `auxiliary/foo.rs` will be named
             // `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so
             // put bins in a `bin` subfolder.
@@ -1250,8 +1278,12 @@ impl<'test> TestCx<'test> {
             aux_rustc.env_remove(key);
         }
 
-        let (aux_type, crate_type) = if is_bin {
+        let (aux_type, crate_type) = if aux_type == Some(AuxType::Bin) {
             (AuxType::Bin, Some("bin"))
+        } else if aux_type == Some(AuxType::ProcMacro) {
+            (AuxType::ProcMacro, Some("proc-macro"))
+        } else if aux_type.is_some() {
+            panic!("aux_type {aux_type:?} not expected");
         } else if aux_props.no_prefer_dynamic {
             (AuxType::Dylib, None)
         } else if self.config.target.contains("emscripten")
@@ -1287,6 +1319,11 @@ impl<'test> TestCx<'test> {
             aux_rustc.args(&["--crate-type", crate_type]);
         }
 
+        if aux_type == AuxType::ProcMacro {
+            // For convenience, but this only works on 2018.
+            aux_rustc.args(&["--extern", "proc_macro"]);
+        }
+
         aux_rustc.arg("-L").arg(&aux_dir);
 
         let auxres = aux_cx.compose_and_run(
@@ -1839,18 +1876,18 @@ impl<'test> TestCx<'test> {
 
     fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
         if self.config.verbose {
-            println!("------stdout------------------------------");
-            println!("{}", out);
-            println!("------stderr------------------------------");
-            println!("{}", err);
-            println!("------------------------------------------");
+            eprintln!("------stdout------------------------------");
+            eprintln!("{}", out);
+            eprintln!("------stderr------------------------------");
+            eprintln!("{}", err);
+            eprintln!("------------------------------------------");
         }
     }
 
     fn error(&self, err: &str) {
         match self.revision {
-            Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
-            None => println!("\nerror: {}", err),
+            Some(rev) => eprintln!("\nerror in revision `{}`: {}", rev, err),
+            None => eprintln!("\nerror: {}", err),
         }
     }
 
@@ -1935,7 +1972,7 @@ impl<'test> TestCx<'test> {
         if !self.config.has_html_tidy {
             return;
         }
-        println!("info: generating a diff against nightly rustdoc");
+        eprintln!("info: generating a diff against nightly rustdoc");
 
         let suffix =
             self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
@@ -2045,7 +2082,7 @@ impl<'test> TestCx<'test> {
                 .output()
                 .unwrap();
             assert!(output.status.success());
-            println!("{}", String::from_utf8_lossy(&output.stdout));
+            eprintln!("{}", String::from_utf8_lossy(&output.stdout));
             eprintln!("{}", String::from_utf8_lossy(&output.stderr));
         } else {
             use colored::Colorize;
@@ -2258,17 +2295,31 @@ impl<'test> TestCx<'test> {
         match output_kind {
             TestOutput::Compile => {
                 if !self.props.dont_check_compiler_stdout {
-                    errors +=
-                        self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
+                    errors += self.compare_output(
+                        stdout_kind,
+                        &normalized_stdout,
+                        &proc_res.stdout,
+                        &expected_stdout,
+                    );
                 }
                 if !self.props.dont_check_compiler_stderr {
-                    errors +=
-                        self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
+                    errors += self.compare_output(
+                        stderr_kind,
+                        &normalized_stderr,
+                        &stderr,
+                        &expected_stderr,
+                    );
                 }
             }
             TestOutput::Run => {
-                errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
-                errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
+                errors += self.compare_output(
+                    stdout_kind,
+                    &normalized_stdout,
+                    &proc_res.stdout,
+                    &expected_stdout,
+                );
+                errors +=
+                    self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr);
             }
         }
         errors
@@ -2445,7 +2496,7 @@ impl<'test> TestCx<'test> {
                 )"#
             )
             .replace_all(&output, |caps: &Captures<'_>| {
-                println!("{}", &caps[0]);
+                eprintln!("{}", &caps[0]);
                 caps[0].replace(r"\", "/")
             })
             .replace("\r\n", "\n")
@@ -2496,7 +2547,13 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize {
+    fn compare_output(
+        &self,
+        stream: &str,
+        actual: &str,
+        actual_unnormalized: &str,
+        expected: &str,
+    ) -> usize {
         let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
             // FIXME: We ignore the first line of SVG files
             // because the width parameter is non-deterministic.
@@ -2507,13 +2564,10 @@ impl<'test> TestCx<'test> {
             return 0;
         }
 
-        // If `compare-output-lines-by-subset` is not explicitly enabled then
-        // auto-enable it when a `runner` is in use since wrapper tools might
-        // provide extra output on failure, for example a WebAssembly runtime
-        // might print the stack trace of an `unreachable` instruction by
-        // default.
-        let compare_output_by_lines =
-            self.props.compare_output_lines_by_subset || self.config.runner.is_some();
+        // Wrapper tools set by `runner` might provide extra output on failure,
+        // for example a WebAssembly runtime might print the stack trace of an
+        // `unreachable` instruction by default.
+        let compare_output_by_lines = self.config.runner.is_some();
 
         let tmp;
         let (expected, actual): (&str, &str) = if compare_output_by_lines {
@@ -2547,37 +2601,23 @@ impl<'test> TestCx<'test> {
         if let Err(err) = fs::write(&actual_path, &actual) {
             self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",));
         }
-        println!("Saved the actual {stream} to {actual_path:?}");
+        eprintln!("Saved the actual {stream} to {actual_path:?}");
 
         let expected_path =
             expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
 
         if !self.config.bless {
             if expected.is_empty() {
-                println!("normalized {}:\n{}\n", stream, actual);
+                eprintln!("normalized {}:\n{}\n", stream, actual);
             } else {
-                println!("diff of {stream}:\n");
-                if let Some(diff_command) = self.config.diff_command.as_deref() {
-                    let mut args = diff_command.split_whitespace();
-                    let name = args.next().unwrap();
-                    match Command::new(name)
-                        .args(args)
-                        .args([&expected_path, &actual_path])
-                        .output()
-                    {
-                        Err(err) => {
-                            self.fatal(&format!(
-                                "failed to call custom diff command `{diff_command}`: {err}"
-                            ));
-                        }
-                        Ok(output) => {
-                            let output = String::from_utf8_lossy(&output.stdout);
-                            print!("{output}");
-                        }
-                    }
-                } else {
-                    print!("{}", write_diff(expected, actual, 3));
-                }
+                self.show_diff(
+                    stream,
+                    &expected_path,
+                    &actual_path,
+                    expected,
+                    actual,
+                    actual_unnormalized,
+                );
             }
         } else {
             // Delete non-revision .stderr/.stdout file if revisions are used.
@@ -2591,14 +2631,84 @@ impl<'test> TestCx<'test> {
             if let Err(err) = fs::write(&expected_path, &actual) {
                 self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
             }
-            println!("Blessing the {stream} of {test_name} in {expected_path:?}");
+            eprintln!("Blessing the {stream} of {test_name} in {expected_path:?}");
         }
 
-        println!("\nThe actual {0} differed from the expected {0}.", stream);
+        eprintln!("\nThe actual {0} differed from the expected {0}.", stream);
 
         if self.config.bless { 0 } else { 1 }
     }
 
+    /// Returns whether to show the full stderr/stdout.
+    fn show_diff(
+        &self,
+        stream: &str,
+        expected_path: &Path,
+        actual_path: &Path,
+        expected: &str,
+        actual: &str,
+        actual_unnormalized: &str,
+    ) {
+        eprintln!("diff of {stream}:\n");
+        if let Some(diff_command) = self.config.diff_command.as_deref() {
+            let mut args = diff_command.split_whitespace();
+            let name = args.next().unwrap();
+            match Command::new(name).args(args).args([expected_path, actual_path]).output() {
+                Err(err) => {
+                    self.fatal(&format!(
+                        "failed to call custom diff command `{diff_command}`: {err}"
+                    ));
+                }
+                Ok(output) => {
+                    let output = String::from_utf8_lossy(&output.stdout);
+                    eprint!("{output}");
+                }
+            }
+        } else {
+            eprint!("{}", write_diff(expected, actual, 3));
+        }
+
+        // NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below.
+        let diff_results = make_diff(actual, expected, 0);
+
+        let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]);
+        for hunk in diff_results {
+            let mut line_no = hunk.line_number;
+            for line in hunk.lines {
+                // NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up
+                if let DiffLine::Expected(normalized) = line {
+                    mismatches_normalized += &normalized;
+                    mismatches_normalized += "\n";
+                    mismatch_line_nos.push(line_no);
+                    line_no += 1;
+                }
+            }
+        }
+        let mut mismatches_unnormalized = String::new();
+        let diff_normalized = make_diff(actual, actual_unnormalized, 0);
+        for hunk in diff_normalized {
+            if mismatch_line_nos.contains(&hunk.line_number) {
+                for line in hunk.lines {
+                    if let DiffLine::Resulting(unnormalized) = line {
+                        mismatches_unnormalized += &unnormalized;
+                        mismatches_unnormalized += "\n";
+                    }
+                }
+            }
+        }
+
+        let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0);
+        // HACK: instead of checking if each hunk is empty, this only checks if the whole input is empty. we should be smarter about this so we don't treat added or removed output as normalized.
+        if !normalized_diff.is_empty()
+            && !mismatches_unnormalized.is_empty()
+            && !mismatches_normalized.is_empty()
+        {
+            eprintln!("Note: some mismatched output was normalized before being compared");
+            // FIXME: respect diff_command
+            eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0));
+        }
+    }
+
     fn check_and_prune_duplicate_outputs(
         &self,
         proc_res: &ProcRes,
@@ -2673,7 +2783,7 @@ impl<'test> TestCx<'test> {
         fs::create_dir_all(&incremental_dir).unwrap();
 
         if self.config.verbose {
-            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+            eprintln!("init_incremental_test: incremental_dir={}", incremental_dir.display());
         }
     }
 
@@ -2731,7 +2841,7 @@ impl ProcRes {
             }
         }
 
-        println!(
+        eprintln!(
             "status: {}\ncommand: {}\n{}\n{}\n",
             self.status,
             self.cmdline,
@@ -2742,7 +2852,7 @@ impl ProcRes {
 
     pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
         if let Some(e) = err {
-            println!("\nerror: {}", e);
+            eprintln!("\nerror: {}", e);
         }
         self.print_info();
         on_failure();
@@ -2768,8 +2878,10 @@ enum LinkToAux {
     No,
 }
 
+#[derive(Debug, PartialEq)]
 enum AuxType {
     Bin,
     Lib,
     Dylib,
+    ProcMacro,
 }
diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs
index 6c866cbef21..6acd140183d 100644
--- a/src/tools/compiletest/src/runtest/codegen_units.rs
+++ b/src/tools/compiletest/src/runtest/codegen_units.rs
@@ -64,13 +64,13 @@ impl TestCx<'_> {
         if !missing.is_empty() {
             missing.sort();
 
-            println!("\nThese items should have been contained but were not:\n");
+            eprintln!("\nThese items should have been contained but were not:\n");
 
             for item in &missing {
-                println!("{}", item);
+                eprintln!("{}", item);
             }
 
-            println!("\n");
+            eprintln!("\n");
         }
 
         if !unexpected.is_empty() {
@@ -80,24 +80,24 @@ impl TestCx<'_> {
                 sorted
             };
 
-            println!("\nThese items were contained but should not have been:\n");
+            eprintln!("\nThese items were contained but should not have been:\n");
 
             for item in sorted {
-                println!("{}", item);
+                eprintln!("{}", item);
             }
 
-            println!("\n");
+            eprintln!("\n");
         }
 
         if !wrong_cgus.is_empty() {
             wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
-            println!("\nThe following items were assigned to wrong codegen units:\n");
+            eprintln!("\nThe following items were assigned to wrong codegen units:\n");
 
             for &(ref expected_item, ref actual_item) in &wrong_cgus {
-                println!("{}", expected_item.name);
-                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
-                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
-                println!();
+                eprintln!("{}", expected_item.name);
+                eprintln!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
+                eprintln!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
+                eprintln!();
             }
         }
 
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 961a1602986..030ca5ebb24 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -39,8 +39,12 @@ impl<'test> TestCx<'test> {
         let expected_coverage_dump = self.load_expected_output(kind);
         let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);
 
-        let coverage_dump_errors =
-            self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump);
+        let coverage_dump_errors = self.compare_output(
+            kind,
+            &actual_coverage_dump,
+            &proc_res.stdout,
+            &expected_coverage_dump,
+        );
 
         if coverage_dump_errors > 0 {
             self.fatal_proc_rec(
@@ -135,8 +139,12 @@ impl<'test> TestCx<'test> {
                 self.fatal_proc_rec(&err, &proc_res);
             });
 
-        let coverage_errors =
-            self.compare_output(kind, &normalized_actual_coverage, &expected_coverage);
+        let coverage_errors = self.compare_output(
+            kind,
+            &normalized_actual_coverage,
+            &proc_res.stdout,
+            &expected_coverage,
+        );
 
         if coverage_errors > 0 {
             self.fatal_proc_rec(
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index c621c22ac99..7322e730e53 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -260,7 +260,7 @@ impl TestCx<'_> {
                 cmdline,
             };
             if adb.kill().is_err() {
-                println!("Adb process is already finished.");
+                eprintln!("Adb process is already finished.");
             }
         } else {
             let rust_src_root =
@@ -275,7 +275,7 @@ impl TestCx<'_> {
 
             match self.config.gdb_version {
                 Some(version) => {
-                    println!("NOTE: compiletest thinks it is using GDB version {}", version);
+                    eprintln!("NOTE: compiletest thinks it is using GDB version {}", version);
 
                     if version > extract_gdb_version("7.4").unwrap() {
                         // Add the directory containing the pretty printers to
@@ -297,7 +297,7 @@ impl TestCx<'_> {
                     }
                 }
                 _ => {
-                    println!(
+                    eprintln!(
                         "NOTE: compiletest does not know which version of \
                          GDB it is using"
                     );
@@ -392,10 +392,10 @@ impl TestCx<'_> {
 
         match self.config.lldb_version {
             Some(ref version) => {
-                println!("NOTE: compiletest thinks it is using LLDB version {}", version);
+                eprintln!("NOTE: compiletest thinks it is using LLDB version {}", version);
             }
             _ => {
-                println!(
+                eprintln!(
                     "NOTE: compiletest does not know which version of \
                      LLDB it is using"
                 );
diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs
index 591aff0defe..4f26786129b 100644
--- a/src/tools/compiletest/src/runtest/incremental.rs
+++ b/src/tools/compiletest/src/runtest/incremental.rs
@@ -30,7 +30,7 @@ impl TestCx<'_> {
         assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
 
         if self.config.verbose {
-            print!("revision={:?} props={:#?}", revision, self.props);
+            eprint!("revision={:?} props={:#?}", revision, self.props);
         }
 
         if revision.starts_with("cpass") {
diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs
index d1ec0035744..64a2addaa28 100644
--- a/src/tools/compiletest/src/runtest/mir_opt.rs
+++ b/src/tools/compiletest/src/runtest/mir_opt.rs
@@ -89,7 +89,7 @@ impl TestCx<'_> {
                 }
                 let expected_string = fs::read_to_string(&expected_file).unwrap();
                 if dumped_string != expected_string {
-                    print!("{}", write_diff(&expected_string, &dumped_string, 3));
+                    eprint!("{}", write_diff(&expected_string, &dumped_string, 3));
                     panic!(
                         "Actual MIR output differs from expected MIR output {}",
                         expected_file.display()
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
index 31fdb0a5d13..84376d346af 100644
--- a/src/tools/compiletest/src/runtest/rustdoc_json.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -29,7 +29,7 @@ impl TestCx<'_> {
 
         if !res.status.success() {
             self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
-                println!("Rustdoc Output:");
+                eprintln!("Rustdoc Output:");
                 proc_res.print_info();
             })
         }
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index bb747c68029..bc860bf18c7 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -100,7 +100,7 @@ impl TestCx<'_> {
                 )
             });
 
-            errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
+            errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed);
         } else if !expected_fixed.is_empty() {
             panic!(
                 "the `//@ run-rustfix` directive wasn't found but a `*.fixed` \
@@ -109,10 +109,10 @@ impl TestCx<'_> {
         }
 
         if errors > 0 {
-            println!("To update references, rerun the tests and pass the `--bless` flag");
+            eprintln!("To update references, rerun the tests and pass the `--bless` flag");
             let relative_path_to_file =
                 self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
-            println!(
+            eprintln!(
                 "To only update this specific test, also pass `--test-args {}`",
                 relative_path_to_file.display(),
             );
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index bff02f1db9f..7b50e62c29b 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -30,7 +30,7 @@ fn path_div() -> &'static str {
 pub fn logv(config: &Config, s: String) {
     debug!("{}", s);
     if config.verbose {
-        println!("{}", s);
+        eprintln!("{}", s);
     }
 }
 
diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs
index 9f95f9fb408..47512039740 100644
--- a/src/tools/jsondocck/src/cache.rs
+++ b/src/tools/jsondocck/src/cache.rs
@@ -28,7 +28,8 @@ impl Cache {
         }
     }
 
-    pub fn value(&self) -> &Value {
-        &self.value
+    // FIXME: Make this failible, so jsonpath syntax error has line number.
+    pub fn select(&self, path: &str) -> Vec<&Value> {
+        jsonpath_lib::select(&self.value, path).unwrap()
     }
 }
diff --git a/src/tools/jsondocck/src/error.rs b/src/tools/jsondocck/src/error.rs
index c4cd79a64fd..0a3e085b405 100644
--- a/src/tools/jsondocck/src/error.rs
+++ b/src/tools/jsondocck/src/error.rs
@@ -1,29 +1,7 @@
-use std::error::Error;
-use std::fmt;
-
 use crate::Command;
 
 #[derive(Debug)]
-pub enum CkError {
-    /// A check failed. File didn't exist or failed to match the command
-    FailedCheck(String, Command),
-    /// An error triggered by some other error
-    Induced(Box<dyn Error>),
-}
-
-impl fmt::Display for CkError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            CkError::FailedCheck(msg, cmd) => {
-                write!(f, "Failed check: {} on line {}", msg, cmd.lineno)
-            }
-            CkError::Induced(err) => write!(f, "Check failed: {}", err),
-        }
-    }
-}
-
-impl<T: Error + 'static> From<T> for CkError {
-    fn from(err: T) -> CkError {
-        CkError::Induced(Box::new(err))
-    }
+pub struct CkError {
+    pub message: String,
+    pub command: Command,
 }
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index c08bbbc769a..b6a1d7dfa7a 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -1,8 +1,8 @@
 use std::borrow::Cow;
+use std::process::ExitCode;
 use std::sync::OnceLock;
-use std::{env, fmt, fs};
+use std::{env, fs};
 
-use jsonpath_lib::select;
 use regex::{Regex, RegexBuilder};
 use serde_json::Value;
 
@@ -14,90 +14,134 @@ use cache::Cache;
 use config::parse_config;
 use error::CkError;
 
-fn main() -> Result<(), String> {
+fn main() -> ExitCode {
     let config = parse_config(env::args().collect());
 
     let mut failed = Vec::new();
     let mut cache = Cache::new(&config);
-    let commands = get_commands(&config.template)
-        .map_err(|_| format!("Jsondocck failed for {}", &config.template))?;
+    let Ok(commands) = get_commands(&config.template) else {
+        eprintln!("Jsondocck failed for {}", &config.template);
+        return ExitCode::FAILURE;
+    };
 
     for command in commands {
-        if let Err(e) = check_command(command, &mut cache) {
-            failed.push(e);
+        if let Err(message) = check_command(&command, &mut cache) {
+            failed.push(CkError { command, message });
         }
     }
 
     if failed.is_empty() {
-        Ok(())
+        ExitCode::SUCCESS
     } else {
         for i in failed {
-            eprintln!("{}", i);
+            eprintln!("{}:{}, command failed", config.template, i.command.lineno);
+            eprintln!("{}", i.message)
         }
-        Err(format!("Jsondocck failed for {}", &config.template))
+        ExitCode::FAILURE
     }
 }
 
 #[derive(Debug)]
 pub struct Command {
-    negated: bool,
     kind: CommandKind,
-    args: Vec<String>,
+    path: String,
     lineno: usize,
 }
 
 #[derive(Debug)]
-pub enum CommandKind {
-    Has,
-    Count,
-    Is,
-    IsMany,
-    Set,
+enum CommandKind {
+    /// `//@ has <path>`
+    ///
+    /// Checks the path exists.
+    HasPath,
+
+    /// `//@ has <path> <value>`
+    ///
+    /// Check one thing at the path  is equal to the value.
+    HasValue { value: String },
+
+    /// `//@ !has <path>`
+    ///
+    /// Checks the path doesn't exist.
+    HasNotPath,
+
+    /// `//@ is <path> <value>`
+    ///
+    /// Check the path is the given value.
+    Is { value: String },
+
+    /// `//@ is <path> <value> <value>...`
+    ///
+    /// Check that the path matches to exactly every given value.
+    IsMany { values: Vec<String> },
+
+    /// `//@ !is <path> <value>`
+    ///
+    /// Check the path isn't the given value.
+    IsNot { value: String },
+
+    /// `//@ count <path> <value>`
+    ///
+    /// Check the path has the expected number of matches.
+    CountIs { expected: usize },
+
+    /// `//@ set <name> = <path>`
+    Set { variable: String },
 }
 
 impl CommandKind {
-    fn validate(&self, args: &[String], lineno: usize) -> bool {
-        // FIXME(adotinthevoid): We should "parse, don't validate" here, so we avoid ad-hoc
-        // indexing in check_command.
-        let count = match self {
-            CommandKind::Has => (1..=2).contains(&args.len()),
-            CommandKind::IsMany => args.len() >= 2,
-            CommandKind::Count | CommandKind::Is => 2 == args.len(),
-            CommandKind::Set => 3 == args.len(),
-        };
+    /// Returns both the kind and the path.
+    ///
+    /// Returns `None` if the command isn't from jsondocck (e.g. from compiletest).
+    fn parse<'a>(command_name: &str, negated: bool, args: &'a [String]) -> Option<(Self, &'a str)> {
+        let kind = match (command_name, negated) {
+            ("count", false) => {
+                assert_eq!(args.len(), 2);
+                let expected = args[1].parse().expect("invalid number for `count`");
+                Self::CountIs { expected }
+            }
 
-        if !count {
-            print_err(&format!("Incorrect number of arguments to `{}`", self), lineno);
-            return false;
-        }
+            ("ismany", false) => {
+                // FIXME: Make this >= 3, and migrate len(values)==1 cases to @is
+                assert!(args.len() >= 2, "Not enough args to `ismany`");
+                let values = args[1..].to_owned();
+                Self::IsMany { values }
+            }
 
-        if let CommandKind::Count = self {
-            if args[1].parse::<usize>().is_err() {
-                print_err(
-                    &format!(
-                        "Second argument to `count` must be a valid usize (got `{}`)",
-                        args[1]
-                    ),
-                    lineno,
-                );
-                return false;
+            ("is", false) => {
+                assert_eq!(args.len(), 2);
+                Self::Is { value: args[1].clone() }
+            }
+            ("is", true) => {
+                assert_eq!(args.len(), 2);
+                Self::IsNot { value: args[1].clone() }
             }
-        }
 
-        true
-    }
-}
+            ("set", false) => {
+                assert_eq!(args.len(), 3);
+                assert_eq!(args[1], "=");
+                return Some((Self::Set { variable: args[0].clone() }, &args[2]));
+            }
 
-impl fmt::Display for CommandKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let text = match self {
-            CommandKind::Has => "has",
-            CommandKind::IsMany => "ismany",
-            CommandKind::Count => "count",
-            CommandKind::Is => "is",
-            CommandKind::Set => "set",
+            ("has", false) => match args {
+                [_path] => Self::HasPath,
+                [_path, value] => Self::HasValue { value: value.clone() },
+                _ => panic!("`//@ has` must have 2 or 3 arguments, but got {args:?}"),
+            },
+            ("has", true) => {
+                assert_eq!(args.len(), 1, "args={args:?}");
+                Self::HasNotPath
+            }
+
+            (_, false) if KNOWN_DIRECTIVE_NAMES.contains(&command_name) => {
+                return None;
+            }
+            _ => {
+                panic!("Invalid command `//@ {}{command_name}`", if negated { "!" } else { "" })
+            }
         };
-        write!(f, "{}", text)
+
+        Some((kind, &args[0]))
     }
 }
 
@@ -125,8 +169,7 @@ fn print_err(msg: &str, lineno: usize) {
 //        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
 include!(concat!(env!("CARGO_MANIFEST_DIR"), "/../compiletest/src/directive-list.rs"));
 
-/// Get a list of commands from a file. Does the work of ensuring the commands
-/// are syntactically valid.
+/// Get a list of commands from a file.
 fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
     let mut commands = Vec::new();
     let mut errors = false;
@@ -142,217 +185,102 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
 
         let negated = cap.name("negated").unwrap().as_str() == "!";
 
-        let cmd = match cap.name("cmd").unwrap().as_str() {
-            "has" => CommandKind::Has,
-            "count" => CommandKind::Count,
-            "is" => CommandKind::Is,
-            "ismany" => CommandKind::IsMany,
-            "set" => CommandKind::Set,
-            // FIXME: See the comment above the `include!(...)`.
-            cmd if KNOWN_DIRECTIVE_NAMES.contains(&cmd) => continue,
-            cmd => {
-                print_err(&format!("Unrecognized command name `{cmd}`"), lineno);
-                errors = true;
-                continue;
-            }
-        };
-
-        let args = cap.name("args").map_or(Some(vec![]), |m| shlex::split(m.as_str()));
-
-        let args = match args {
+        let args_str = &cap["args"];
+        let args = match shlex::split(args_str) {
             Some(args) => args,
             None => {
-                print_err(
-                    &format!(
-                        "Invalid arguments to shlex::split: `{}`",
-                        cap.name("args").unwrap().as_str()
-                    ),
-                    lineno,
-                );
+                print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno);
                 errors = true;
                 continue;
             }
         };
 
-        if !cmd.validate(&args, lineno) {
-            errors = true;
-            continue;
+        if let Some((kind, path)) = CommandKind::parse(&cap["cmd"], negated, &args) {
+            commands.push(Command { kind, lineno, path: path.to_owned() })
         }
-
-        commands.push(Command { negated, kind: cmd, args, lineno })
     }
 
     if !errors { Ok(commands) } else { Err(()) }
 }
 
-/// Performs the actual work of ensuring a command passes. Generally assumes the command
-/// is syntactically valid.
-fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
-    // FIXME: Be more granular about why, (e.g. syntax error, count not equal)
-    let result = match command.kind {
-        CommandKind::Has => {
-            match command.args.len() {
-                // `has <jsonpath>`: Check that `jsonpath` exists.
-                1 => {
-                    let val = cache.value();
-                    let results = select(val, &command.args[0]).unwrap();
-                    !results.is_empty()
-                }
-                // `has <jsonpath> <value>`: Check *any* item matched by `jsonpath` equals `value`.
-                2 => {
-                    let val = cache.value().clone();
-                    let results = select(&val, &command.args[0]).unwrap();
-                    let pat = string_to_value(&command.args[1], cache);
-                    let has = results.contains(&pat.as_ref());
-                    // Give better error for when `has` check fails.
-                    if !command.negated && !has {
-                        return Err(CkError::FailedCheck(
-                            format!(
-                                "{} matched to {:?} but didn't have {:?}",
-                                &command.args[0],
-                                results,
-                                pat.as_ref()
-                            ),
-                            command,
-                        ));
-                    } else {
-                        has
-                    }
-                }
-                _ => unreachable!(),
+/// Performs the actual work of ensuring a command passes.
+fn check_command(command: &Command, cache: &mut Cache) -> Result<(), String> {
+    let matches = cache.select(&command.path);
+    match &command.kind {
+        CommandKind::HasPath => {
+            if matches.is_empty() {
+                return Err("matched to no values".to_owned());
+            }
+        }
+        CommandKind::HasNotPath => {
+            if !matches.is_empty() {
+                return Err(format!("matched to {matches:?}, but wanted no matches"));
+            }
+        }
+        CommandKind::HasValue { value } => {
+            let want_value = string_to_value(value, cache);
+            if !matches.contains(&want_value.as_ref()) {
+                return Err(format!("matched to {matches:?}, which didn't contain {want_value:?}"));
+            }
+        }
+        CommandKind::Is { value } => {
+            let want_value = string_to_value(value, cache);
+            let matched = get_one(&matches)?;
+            if matched != want_value.as_ref() {
+                return Err(format!("matched to {matched:?} but want {want_value:?}"));
+            }
+        }
+        CommandKind::IsNot { value } => {
+            let wantnt_value = string_to_value(value, cache);
+            let matched = get_one(&matches)?;
+            if matched == wantnt_value.as_ref() {
+                return Err(format!("got value {wantnt_value:?}, but want anything else"));
             }
         }
-        // `ismany <path> <jsonpath> <value...>`
-        CommandKind::IsMany => {
-            assert!(!command.negated, "`ismany` may not be negated");
-            let (query, values) = if let [query, values @ ..] = &command.args[..] {
-                (query, values)
-            } else {
-                unreachable!("Checked in CommandKind::validate")
-            };
-            let val = cache.value();
-            let got_values = select(val, &query).unwrap();
 
+        CommandKind::IsMany { values } => {
             // Serde json doesn't implement Ord or Hash for Value, so we must
             // use a Vec here. While in theory that makes setwize equality
             // O(n^2), in practice n will never be large enough to matter.
             let expected_values =
                 values.iter().map(|v| string_to_value(v, cache)).collect::<Vec<_>>();
-            if expected_values.len() != got_values.len() {
-                return Err(CkError::FailedCheck(
-                    format!(
-                        "Expected {} values, but `{}` matched to {} values ({:?})",
-                        expected_values.len(),
-                        query,
-                        got_values.len(),
-                        got_values
-                    ),
-                    command,
+            if expected_values.len() != matches.len() {
+                return Err(format!(
+                    "Expected {} values, but matched to {} values ({:?})",
+                    expected_values.len(),
+                    matches.len(),
+                    matches
                 ));
             };
-            for got_value in got_values {
+            for got_value in matches {
                 if !expected_values.iter().any(|exp| &**exp == got_value) {
-                    return Err(CkError::FailedCheck(
-                        format!("`{}` has match {:?}, which was not expected", query, got_value),
-                        command,
-                    ));
+                    return Err(format!("has match {got_value:?}, which was not expected",));
                 }
             }
-            true
-        }
-        // `count <jsonpath> <count>`: Check that `jsonpath` matches exactly `count` times.
-        CommandKind::Count => {
-            assert_eq!(command.args.len(), 2);
-            let expected: usize = command.args[1].parse().unwrap();
-            let val = cache.value();
-            let results = select(val, &command.args[0]).unwrap();
-            let eq = results.len() == expected;
-            if !command.negated && !eq {
-                return Err(CkError::FailedCheck(
-                    format!(
-                        "`{}` matched to `{:?}` with length {}, but expected length {}",
-                        &command.args[0],
-                        results,
-                        results.len(),
-                        expected
-                    ),
-                    command,
-                ));
-            } else {
-                eq
-            }
         }
-        // `has <jsonpath> <value>`: Check` *exactly one* item matched by `jsonpath`, and it equals `value`.
-        CommandKind::Is => {
-            assert_eq!(command.args.len(), 2);
-            let val = cache.value().clone();
-            let results = select(&val, &command.args[0]).unwrap();
-            let pat = string_to_value(&command.args[1], cache);
-            let is = results.len() == 1 && results[0] == pat.as_ref();
-            if !command.negated && !is {
-                return Err(CkError::FailedCheck(
-                    format!(
-                        "{} matched to {:?}, but expected {:?}",
-                        &command.args[0],
-                        results,
-                        pat.as_ref()
-                    ),
-                    command,
+        CommandKind::CountIs { expected } => {
+            if *expected != matches.len() {
+                return Err(format!(
+                    "matched to `{matches:?}` with length {}, but expected length {expected}",
+                    matches.len(),
                 ));
-            } else {
-                is
             }
         }
-        // `set <name> = <jsonpath>`
-        CommandKind::Set => {
-            assert!(!command.negated, "`set` may not be negated");
-            assert_eq!(command.args.len(), 3);
-            assert_eq!(command.args[1], "=", "Expected an `=`");
-            let val = cache.value().clone();
-            let results = select(&val, &command.args[2]).unwrap();
-            assert_eq!(
-                results.len(),
-                1,
-                "Expected 1 match for `{}` (because of `set`): matched to {:?}",
-                command.args[2],
-                results
-            );
-            match results.len() {
-                0 => false,
-                1 => {
-                    let r = cache.variables.insert(command.args[0].clone(), results[0].clone());
-                    assert!(r.is_none(), "Name collision: {} is duplicated", command.args[0]);
-                    true
-                }
-                _ => {
-                    panic!(
-                        "Got multiple results in `set` for `{}`: {:?}",
-                        &command.args[2], results,
-                    );
-                }
-            }
+        CommandKind::Set { variable } => {
+            let value = get_one(&matches)?;
+            let r = cache.variables.insert(variable.to_owned(), value.clone());
+            assert!(r.is_none(), "name collision: {variable:?} is duplicated");
         }
-    };
+    }
 
-    if result == command.negated {
-        if command.negated {
-            Err(CkError::FailedCheck(
-                format!("`!{} {}` matched when it shouldn't", command.kind, command.args.join(" ")),
-                command,
-            ))
-        } else {
-            // FIXME: In the future, try 'peeling back' each step, and see at what level the match failed
-            Err(CkError::FailedCheck(
-                format!(
-                    "`{} {}` didn't match when it should",
-                    command.kind,
-                    command.args.join(" ")
-                ),
-                command,
-            ))
-        }
-    } else {
-        Ok(())
+    Ok(())
+}
+
+fn get_one<'a>(matches: &[&'a Value]) -> Result<&'a Value, String> {
+    match matches {
+        [] => Err("matched to no values".to_owned()),
+        [matched] => Ok(matched),
+        _ => Err(format!("matched to multiple values {matches:?}, but want exactly 1")),
     }
 }
 
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 05d1c2d1eb3..363b96fdff1 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "addr2line"
@@ -151,12 +151,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
-name = "cfg_aliases"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
-
-[[package]]
 name = "chrono"
 version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -287,16 +281,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "ctrlc"
-version = "3.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
-dependencies = [
- "nix",
- "windows-sys 0.52.0",
-]
-
-[[package]]
 name = "directories"
 version = "5.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -420,16 +404,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
-name = "jemalloc-sys"
-version = "0.5.4+5.3.0-patched"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
 name = "lazy_static"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -554,10 +528,8 @@ dependencies = [
  "chrono",
  "chrono-tz",
  "colored",
- "ctrlc",
  "directories",
  "getrandom",
- "jemalloc-sys",
  "libc",
  "libffi",
  "libloading",
@@ -567,23 +539,12 @@ dependencies = [
  "rustc_version",
  "smallvec",
  "tempfile",
+ "tikv-jemalloc-sys",
  "ui_test",
  "windows-sys 0.52.0",
 ]
 
 [[package]]
-name = "nix"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
-]
-
-[[package]]
 name = "num-traits"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1032,6 +993,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "tikv-jemalloc-sys"
+version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
 name = "tracing"
 version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index cb02914fd93..6e8e270985e 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -23,7 +23,6 @@ rand = "0.8"
 smallvec = { version = "1.7", features = ["drain_filter"] }
 aes = { version = "0.8.3", features = ["hazmat"] }
 measureme = "11"
-ctrlc = "3.2.5"
 chrono = { version = "0.4.38", default-features = false }
 chrono-tz = "0.10"
 directories = "5"
@@ -31,8 +30,8 @@ directories = "5"
 # Copied from `compiler/rustc/Cargo.toml`.
 # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't
 # easily use that since we support of-tree builds.
-[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.jemalloc-sys]
-version = "0.5.0"
+[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys]
+version = "0.6.0"
 features = ['unprefixed_malloc_on_supported_platforms']
 
 [target.'cfg(unix)'.dependencies]
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 9a683ae68fd..4e30dea18ff 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -68,9 +68,10 @@ Further caveats that Miri users should be aware of:
   not support networking. System API support varies between targets; if you run
   on Windows it is a good idea to use `--target x86_64-unknown-linux-gnu` to get
   better support.
-* Weak memory emulation may [produce weak behaviors](https://github.com/rust-lang/miri/issues/2301)
-  when `SeqCst` fences are used that are not actually permitted by the Rust memory model, and it
-  cannot produce all behaviors possibly observable on real hardware.
+* Weak memory emulation is not complete: there are legal behaviors that Miri will never produce.
+  However, Miri produces many behaviors that are hard to observe on real hardware, so it can help
+  quite a bit in finding weak memory concurrency bugs. To be really sure about complicated atomic
+  code, use specialized tools such as [loom](https://github.com/tokio-rs/loom).
 
 Moreover, Miri fundamentally cannot ensure that your code is *sound*. [Soundness] is the property of
 never causing undefined behavior when invoked from arbitrary safe code, even in combination with
diff --git a/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock
new file mode 100644
index 00000000000..443115c1265
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "string-replace"
+version = "0.1.0"
diff --git a/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml
new file mode 100644
index 00000000000..f0785cd693e
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "string-replace"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/miri/bench-cargo-miri/string-replace/data.json b/src/tools/miri/bench-cargo-miri/string-replace/data.json
new file mode 100644
index 00000000000..7e074cd6954
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/string-replace/data.json
@@ -0,0 +1 @@
+[{"_id":"6724e6fc58417687afba2b85","index":0,"guid":"5c1bd108-2ee2-40bd-bce8-895c206409df","isActive":true,"balance":"$2,927.88","picture":"http://placehold.it/32x32","age":40,"eyeColor":"green","name":"Wynn Bradshaw","gender":"male","company":"ROTODYNE","email":"wynnbradshaw@rotodyne.com","phone":"+1 (904) 559-3130","address":"287 Bergen Avenue, Sperryville, Alaska, 5392","about":"Adipisicing fugiat aute adipisicing qui esse cillum. Lorem consequat consectetur voluptate id pariatur nostrud incididunt aliquip incididunt laboris aliqua. Magna nulla adipisicing cupidatat ea velit aliquip magna duis duis sunt ipsum. Cillum labore mollit fugiat tempor dolor sit.\r\n","registered":"2017-01-26T01:28:10 -01:00","latitude":46.089504,"longitude":51.763723,"greeting":"Hello, Wynn Bradshaw! You have 6 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fce8619d86c0389ccf","index":1,"guid":"ced7fbb7-3b1a-419b-9fc7-d47582bbb3ea","isActive":true,"balance":"$1,856.38","picture":"http://placehold.it/32x32","age":21,"eyeColor":"brown","name":"Olsen Larsen","gender":"male","company":"VERBUS","email":"olsenlarsen@verbus.com","phone":"+1 (936) 480-3749","address":"370 Losee Terrace, Churchill, Maine, 4040","about":"Consequat Lorem in laboris fugiat veniam tempor eiusmod eu incididunt enim do et qui. Sit commodo eu excepteur cillum ex tempor commodo ex ex laboris esse. Aute aute nulla dolore dolor do. Irure esse proident nostrud non. Incididunt velit reprehenderit incididunt laboris do. Consequat nulla est id ex veniam tempor. Sit Lorem magna cillum aliquip irure quis sit minim anim.\r\n","registered":"2016-07-12T02:08:39 -02:00","latitude":-12.843628,"longitude":-124.143829,"greeting":"Hello, Olsen Larsen! You have 1 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fc01b471965ea560cf","index":2,"guid":"21fde9a3-13ba-46be-baed-fb503f668b9e","isActive":false,"balance":"$2,025.88","picture":"http://placehold.it/32x32","age":29,"eyeColor":"green","name":"Ramirez Kinney","gender":"male","company":"QUAREX","email":"ramirezkinney@quarex.com","phone":"+1 (852) 447-2930","address":"986 Cornelia Street, Oberlin, Texas, 362","about":"Minim ea proident quis eiusmod aliquip duis excepteur velit minim aute cupidatat. Esse qui ex aliquip laborum id reprehenderit. Anim dolore commodo deserunt laborum nulla duis. Sint quis anim mollit fugiat sit incididunt reprehenderit occaecat aliqua dolor. Ullamco ipsum eiusmod incididunt proident qui exercitation adipisicing voluptate elit aliquip. Tempor duis aute incididunt adipisicing.\r\n","registered":"2016-02-23T05:34:14 -01:00","latitude":-56.21645,"longitude":44.048129,"greeting":"Hello, Ramirez Kinney! You have 9 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fc3ea8e4182b9e170f","index":3,"guid":"46b20637-eecc-40db-87d7-03da9bcd1cea","isActive":true,"balance":"$3,399.31","picture":"http://placehold.it/32x32","age":39,"eyeColor":"brown","name":"Hansen Kaufman","gender":"male","company":"EVENTAGE","email":"hansenkaufman@eventage.com","phone":"+1 (827) 483-2303","address":"916 Brighton Court, Sunbury, New Mexico, 3804","about":"Nisi in voluptate aute ullamco ipsum proident fugiat veniam anim reprehenderit. In ad irure dolor labore culpa incididunt veniam mollit Lorem deserunt cupidatat incididunt. Aliquip aliquip proident ut culpa.\r\n","registered":"2023-10-18T07:03:48 -02:00","latitude":-40.239135,"longitude":49.802049,"greeting":"Hello, Hansen Kaufman! You have 10 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fc721f83a10cf2aa37","index":4,"guid":"3d23743b-1e82-474e-8f7a-855fa46170d1","isActive":false,"balance":"$1,967.87","picture":"http://placehold.it/32x32","age":35,"eyeColor":"green","name":"Imelda Stephens","gender":"female","company":"OHMNET","email":"imeldastephens@ohmnet.com","phone":"+1 (893) 523-2400","address":"391 Wilson Street, Glidden, Kansas, 7226","about":"Officia sunt magna adipisicing id exercitation deserunt deserunt aliquip excepteur Lorem enim fugiat. Nulla culpa ut cupidatat excepteur do deserunt labore id eu laboris ullamco adipisicing ad. Et non nisi adipisicing minim aliquip ea ut qui adipisicing do laboris ex dolore duis.\r\n","registered":"2020-10-20T07:03:38 -02:00","latitude":0.348698,"longitude":-157.961956,"greeting":"Hello, Imelda Stephens! You have 2 unread messages.","favoriteFruit":"strawberry"},{"_id":"6724e6fc7ad7274b9f4c406c","index":5,"guid":"626292b1-ae84-4887-9e29-78e548cd24e6","isActive":true,"balance":"$1,577.44","picture":"http://placehold.it/32x32","age":40,"eyeColor":"brown","name":"Lynne Jarvis","gender":"female","company":"CORECOM","email":"lynnejarvis@corecom.com","phone":"+1 (899) 556-3876","address":"465 National Drive, Davenport, Palau, 9786","about":"Aliquip elit dolore sint quis do laboris exercitation elit aliqua eiusmod. Excepteur ad aliqua eiusmod incididunt tempor laboris officia consectetur sit. Cupidatat voluptate deserunt ut consectetur qui laborum duis elit incididunt occaecat laborum. Mollit aute velit officia amet aute minim fugiat sit laborum Lorem deserunt in. Exercitation eu sunt nulla adipisicing quis ea aute est. Lorem ea cillum ad labore quis minim et est laboris deserunt proident. Amet ut tempor laborum occaecat exercitation ullamco laborum adipisicing fugiat ea voluptate quis fugiat.\r\n","registered":"2018-11-03T03:53:15 -01:00","latitude":89.827087,"longitude":-136.882799,"greeting":"Hello, Lynne Jarvis! You have 3 unread messages.","favoriteFruit":"strawberry"},{"_id":"6724e6fcef1a1db2cf170762","index":6,"guid":"b8777c06-b90f-49a4-8737-96712fc504a3","isActive":false,"balance":"$2,285.03","picture":"http://placehold.it/32x32","age":37,"eyeColor":"green","name":"Price Bolton","gender":"male","company":"IMANT","email":"pricebolton@imant.com","phone":"+1 (825) 424-2873","address":"237 Aberdeen Street, Sattley, Montana, 2918","about":"Non cillum irure fugiat consequat ad ex. Magna magna tempor excepteur irure quis. Duis in laboris ipsum adipisicing culpa magna reprehenderit nisi incididunt est veniam quis. Labore culpa ut culpa veniam est est consectetur ipsum ex esse.\r\n","registered":"2014-04-26T01:20:19 -02:00","latitude":70.349258,"longitude":126.810102,"greeting":"Hello, Price Bolton! You have 10 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fc8bcb952208c159f9","index":7,"guid":"a4e6c6c8-3fe3-42de-ae28-79c16956d309","isActive":false,"balance":"$1,298.07","picture":"http://placehold.it/32x32","age":28,"eyeColor":"blue","name":"Gretchen Wynn","gender":"female","company":"TERASCAPE","email":"gretchenwynn@terascape.com","phone":"+1 (882) 447-2895","address":"973 Suydam Place, Shindler, Nebraska, 8094","about":"Anim mollit labore magna proident ipsum culpa enim deserunt dolore sunt veniam fugiat. Ad fugiat cupidatat nisi commodo dolore duis commodo nostrud est. Enim proident ullamco non adipisicing magna consequat mollit ad reprehenderit laboris. Ex quis duis anim id non commodo amet sunt est magna officia.\r\n","registered":"2021-08-13T08:51:32 -02:00","latitude":14.551848,"longitude":-27.142242,"greeting":"Hello, Gretchen Wynn! You have 7 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fcc8243c2dfa47f5d4","index":8,"guid":"27df20d5-c1d8-419b-ad38-bdd1e6094775","isActive":true,"balance":"$3,005.40","picture":"http://placehold.it/32x32","age":33,"eyeColor":"blue","name":"Chen Travis","gender":"male","company":"MEMORA","email":"chentravis@memora.com","phone":"+1 (980) 500-2406","address":"182 Dahlgreen Place, Baker, South Carolina, 9817","about":"Ad nisi consequat aliquip eiusmod aute pariatur est sint magna. Ad magna anim esse qui Lorem nulla veniam dolore eiusmod. Cillum consequat sit aliqua est proident exercitation eiusmod irure. Minim eu laboris ad incididunt enim sunt. Sunt in excepteur aute non tempor irure mollit laboris. Eu et duis ullamco dolor sint occaecat officia culpa ipsum anim anim eu veniam aliquip. Exercitation ipsum dolor sint cillum duis incididunt minim quis irure enim reprehenderit do do incididunt.\r\n","registered":"2019-09-01T02:57:37 -02:00","latitude":25.442301,"longitude":48.381036,"greeting":"Hello, Chen Travis! You have 1 unread messages.","favoriteFruit":"banana"}]
\ No newline at end of file
diff --git a/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs b/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs
new file mode 100644
index 00000000000..73bf4a850e4
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs
@@ -0,0 +1,7 @@
+const TCB_INFO_JSON: &str = include_str!("../data.json");
+
+fn main() {
+    let tcb_json = TCB_INFO_JSON;
+    let bad_tcb_json = tcb_json.replace("female", "male");
+    std::hint::black_box(bad_tcb_json);
+}
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index f1f76fd338c..7ca4f414c20 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -348,14 +348,17 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
             // Create a stub .d file to stop Cargo from "rebuilding" the crate:
             // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
             // As we store a JSON file instead of building the crate here, an empty file is fine.
-            let dep_info_name = format!(
-                "{}/{}{}.d",
-                get_arg_flag_value("--out-dir").unwrap(),
+            let mut dep_info_name = PathBuf::from(get_arg_flag_value("--out-dir").unwrap());
+            dep_info_name.push(format!(
+                "{}{}.d",
                 get_arg_flag_value("--crate-name").unwrap(),
                 get_arg_flag_value("extra-filename").unwrap_or_default(),
-            );
+            ));
             if verbose > 0 {
-                eprintln!("[cargo-miri rustc] writing stub dep-info to `{dep_info_name}`");
+                eprintln!(
+                    "[cargo-miri rustc] writing stub dep-info to `{}`",
+                    dep_info_name.display()
+                );
             }
             File::create(dep_info_name).expect("failed to create fake .d file");
         }
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 0356d7ecf10..8e6e31bee43 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -152,9 +152,9 @@ case $HOST_TARGET in
     UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
     TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
     TEST_TARGET=i686-unknown-freebsd   run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
-    TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe
-    TEST_TARGET=x86_64-pc-solaris      run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe
-    TEST_TARGET=aarch64-linux-android  run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread
+    TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs
+    TEST_TARGET=x86_64-pc-solaris      run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs
+    TEST_TARGET=aarch64-linux-android  run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd
     TEST_TARGET=wasm32-wasip2          run_tests_minimal $BASIC wasm
     TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
     TEST_TARGET=thumbv7em-none-eabihf  run_tests_minimal no_std
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index effed0cd180..57d0b27dfd3 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-2d0ea7956c45de6e421fd579e2ded27be405dec6
+728f2daab42ba8f1b3d5caab62495798d1eabfa1
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index fe7d8db245b..f7295fd7d8a 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -286,9 +286,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
-        let global_state = this.machine.alloc_addresses.get_mut();
+    fn expose_ptr(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let this = self.eval_context_ref();
+        let mut global_state = this.machine.alloc_addresses.borrow_mut();
         // In strict mode, we don't need this, so we can save some cycles by not tracking it.
         if global_state.provenance_mode == ProvenanceMode::Strict {
             return interp_ok(());
@@ -299,8 +299,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             return interp_ok(());
         }
         trace!("Exposing allocation id {alloc_id:?}");
-        let global_state = this.machine.alloc_addresses.get_mut();
         global_state.exposed.insert(alloc_id);
+        // Release the global state before we call `expose_tag`, which may call `get_alloc_info_extra`,
+        // which may need access to the global state.
+        drop(global_state);
         if this.machine.borrow_tracker.is_some() {
             this.expose_tag(alloc_id, tag)?;
         }
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index c61c62c73da..5248c9d186b 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -3,6 +3,7 @@
     clippy::manual_range_contains,
     clippy::useless_format,
     clippy::field_reassign_with_default,
+    clippy::needless_lifetimes,
     rustc::diagnostic_outside_of_impl,
     rustc::untranslatable_diagnostic
 )]
@@ -289,7 +290,8 @@ fn run_compiler(
     let exit_code = rustc_driver::catch_with_exit_code(move || {
         rustc_driver::RunCompiler::new(&args, callbacks)
             .set_using_internal_features(using_internal_features)
-            .run()
+            .run();
+        Ok(())
     });
     std::process::exit(exit_code)
 }
@@ -316,6 +318,8 @@ fn jemalloc_magic() {
     // See there for further comments.
     use std::os::raw::{c_int, c_void};
 
+    use tikv_jemalloc_sys as jemalloc_sys;
+
     #[used]
     static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc;
     #[used]
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 4883613dea5..9808102f4ba 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -302,8 +302,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
+    fn expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let this = self.eval_context_ref();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
             BorrowTrackerMethod::StackedBorrows => this.sb_expose_tag(alloc_id, tag),
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index a855603eeb3..ea75131078e 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -1011,8 +1011,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Mark the given tag as exposed. It was found on a pointer with the given AllocId.
-    fn sb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
+    fn sb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let this = self.eval_context_ref();
 
         // Function pointers and dead objects don't have an alloc_extra so we ignore them.
         // This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks.
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs
new file mode 100644
index 00000000000..928b3e6baef
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs
@@ -0,0 +1,108 @@
+use super::AccessKind;
+use super::tree::AccessRelatedness;
+
+/// To speed up tree traversals, we want to skip traversing subtrees when we know the traversal will have no effect.
+/// This is often the case for foreign accesses, since usually foreign accesses happen several times in a row, but also
+/// foreign accesses are idempotent. In particular, see tests `foreign_read_is_noop_after_foreign_write` and `all_transitions_idempotent`.
+/// Thus, for each node we keep track of the "strongest idempotent foreign access" (SIFA), i.e. which foreign access can be skipped.
+/// Note that for correctness, it is not required that this is the strongest access, just any access it is idempotent under. In particular, setting
+/// it to `None` is always correct, but the point of this optimization is to have it be as strong as possible so that more accesses can be skipped.
+/// This enum represents the kinds of values we store:
+/// - `None` means that the node (and its subtrees) are not (guaranteed to be) idempotent under any foreign access.
+/// - `Read` means that the node (and its subtrees) are idempotent under foreign reads, but not (yet / necessarily) under foreign writes.
+/// - `Write` means that the node (and its subtrees) are idempotent under foreign writes. This also implies that it is idempotent under foreign
+///   reads, since reads are stronger than writes (see test `foreign_read_is_noop_after_foreign_write`). In other words, this node can be skipped
+///   for all foreign accesses.
+///
+/// Since a traversal does not just visit a node, but instead the entire subtree, the SIFA field for a given node indicates that the access to
+/// *the entire subtree* rooted at that node can be skipped. In order for this to work, we maintain the global invariant that at
+/// each location, the SIFA at each child must be stronger than that at the parent. For normal reads and writes, this is easily accomplished by
+/// tracking each foreign access as it occurs, so that then the next access can be skipped. This also obviously maintains the invariant, because
+/// if a node undergoes a foreign access, then all its children also see this as a foreign access. However, the invariant is broken during retags,
+/// because retags act across the entire allocation, but only emit a read event across a specific range. This means that for all nodes outside that
+/// range, the invariant is potentially broken, since a new child with a weaker SIFA is inserted. Thus, during retags, special care is taken to
+/// "manually" reset the parent's SIFA to be at least as strong as the new child's. This is accomplished with the `ensure_no_stronger_than` method.
+///
+/// Note that we derive Ord and PartialOrd, so the order in which variants are listed below matters:
+/// None < Read < Write. Do not change that order. See the `test_order` test.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
+pub enum IdempotentForeignAccess {
+    #[default]
+    None,
+    Read,
+    Write,
+}
+
+impl IdempotentForeignAccess {
+    /// Returns true if a node where the strongest idempotent foreign access is `self`
+    /// can skip the access `happening_next`. Note that if this returns
+    /// `true`, then the entire subtree will be skipped.
+    pub fn can_skip_foreign_access(self, happening_next: IdempotentForeignAccess) -> bool {
+        debug_assert!(happening_next.is_foreign());
+        // This ordering is correct. Intuitively, if the last access here was
+        // a foreign write, everything can be skipped, since after a foreign write,
+        // all further foreign accesses are idempotent
+        happening_next <= self
+    }
+
+    /// Updates `self` to account for a foreign access.
+    pub fn record_new(&mut self, just_happened: IdempotentForeignAccess) {
+        if just_happened.is_local() {
+            // If the access is local, reset it.
+            *self = IdempotentForeignAccess::None;
+        } else {
+            // Otherwise, keep it or stengthen it.
+            *self = just_happened.max(*self);
+        }
+    }
+
+    /// Returns true if this access is local.
+    pub fn is_local(self) -> bool {
+        matches!(self, IdempotentForeignAccess::None)
+    }
+
+    /// Returns true if this access is foreign, i.e. not local.
+    pub fn is_foreign(self) -> bool {
+        !self.is_local()
+    }
+
+    /// Constructs a foreign access from an `AccessKind`
+    pub fn from_foreign(acc: AccessKind) -> IdempotentForeignAccess {
+        match acc {
+            AccessKind::Read => Self::Read,
+            AccessKind::Write => Self::Write,
+        }
+    }
+
+    /// Usually, tree traversals have an `AccessKind` and an `AccessRelatedness`.
+    /// This methods converts these into the corresponding `IdempotentForeignAccess`, to be used
+    /// to e.g. invoke `can_skip_foreign_access`.
+    pub fn from_acc_and_rel(acc: AccessKind, rel: AccessRelatedness) -> IdempotentForeignAccess {
+        if rel.is_foreign() { Self::from_foreign(acc) } else { Self::None }
+    }
+
+    /// During retags, the SIFA needs to be weakened to account for children with weaker SIFAs being inserted.
+    /// Thus, this method is called from the bottom up on each parent, until it returns false, which means the
+    /// "children have stronger SIFAs" invariant is restored.
+    pub fn ensure_no_stronger_than(&mut self, strongest_allowed: IdempotentForeignAccess) -> bool {
+        if *self > strongest_allowed {
+            *self = strongest_allowed;
+            true
+        } else {
+            false
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::IdempotentForeignAccess;
+
+    #[test]
+    fn test_order() {
+        // The internal logic relies on this order.
+        // Do not change.
+        assert!(IdempotentForeignAccess::None < IdempotentForeignAccess::Read);
+        assert!(IdempotentForeignAccess::Read < IdempotentForeignAccess::Write);
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 8469744bbc4..f39a606513d 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -9,6 +9,7 @@ use crate::concurrency::data_race::NaReadType;
 use crate::*;
 
 pub mod diagnostics;
+mod foreign_access_skipping;
 mod perms;
 mod tree;
 mod unimap;
@@ -296,7 +297,14 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             this.machine.current_span(),
         )?;
         // Record the parent-child pair in the tree.
-        tree_borrows.new_child(orig_tag, new_tag, new_perm.initial_state, range, span)?;
+        tree_borrows.new_child(
+            orig_tag,
+            new_tag,
+            new_perm.initial_state,
+            range,
+            span,
+            new_perm.protector.is_some(),
+        )?;
         drop(tree_borrows);
 
         // Also inform the data race model (but only if any bytes are actually affected).
@@ -532,8 +540,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Mark the given tag as exposed. It was found on a pointer with the given AllocId.
-    fn tb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
+    fn tb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let this = self.eval_context_ref();
 
         // Function pointers and dead objects don't have an alloc_extra so we ignore them.
         // This is okay because accessing them is UB anyway, no need for any Tree Borrows checks.
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
index 28f9dec7bb9..6e157d3fcd3 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -48,6 +48,7 @@ enum PermissionPriv {
     Disabled,
 }
 use self::PermissionPriv::*;
+use super::foreign_access_skipping::IdempotentForeignAccess;
 
 impl PartialOrd for PermissionPriv {
     /// PermissionPriv is ordered by the reflexive transitive closure of
@@ -87,6 +88,28 @@ impl PermissionPriv {
     fn compatible_with_protector(&self) -> bool {
         !matches!(self, ReservedIM)
     }
+
+    /// See `foreign_access_skipping.rs`. Computes the SIFA of a permission.
+    fn strongest_idempotent_foreign_access(&self, prot: bool) -> IdempotentForeignAccess {
+        match self {
+            // A protected non-conflicted Reserved will become conflicted under a foreign read,
+            // and is hence not idempotent under it.
+            ReservedFrz { conflicted } if prot && !conflicted => IdempotentForeignAccess::None,
+            // Otherwise, foreign reads do not affect Reserved
+            ReservedFrz { .. } => IdempotentForeignAccess::Read,
+            // Famously, ReservedIM survives foreign writes. It is never protected.
+            ReservedIM if prot => unreachable!("Protected ReservedIM should not exist!"),
+            ReservedIM => IdempotentForeignAccess::Write,
+            // Active changes on any foreign access (becomes Frozen/Disabled).
+            Active => IdempotentForeignAccess::None,
+            // Frozen survives foreign reads, but not writes.
+            Frozen => IdempotentForeignAccess::Read,
+            // Disabled survives foreign reads and writes. It survives them
+            // even if protected, because a protected `Disabled` is not initialized
+            // and does therefore not trigger UB.
+            Disabled => IdempotentForeignAccess::Write,
+        }
+    }
 }
 
 /// This module controls how each permission individually reacts to an access.
@@ -305,6 +328,13 @@ impl Permission {
             (Disabled, _) => false,
         }
     }
+
+    /// Returns the strongest foreign action this node survives (without change),
+    /// where `prot` indicates if it is protected.
+    /// See `foreign_access_skipping`
+    pub fn strongest_idempotent_foreign_access(&self, prot: bool) -> IdempotentForeignAccess {
+        self.inner.strongest_idempotent_foreign_access(prot)
+    }
 }
 
 impl PermTransition {
@@ -575,7 +605,7 @@ mod propagation_optimization_checks {
     impl Exhaustive for AccessRelatedness {
         fn exhaustive() -> Box<dyn Iterator<Item = Self>> {
             use AccessRelatedness::*;
-            Box::new(vec![This, StrictChildAccess, AncestorAccess, DistantAccess].into_iter())
+            Box::new(vec![This, StrictChildAccess, AncestorAccess, CousinAccess].into_iter())
         }
     }
 
@@ -635,6 +665,35 @@ mod propagation_optimization_checks {
     }
 
     #[test]
+    #[rustfmt::skip]
+    fn permission_sifa_is_correct() {
+        // Tests that `strongest_idempotent_foreign_access` is correct. See `foreign_access_skipping.rs`.
+        for perm in PermissionPriv::exhaustive() {
+            // Assert that adding a protector makes it less idempotent.
+            if perm.compatible_with_protector() {
+                assert!(perm.strongest_idempotent_foreign_access(true) <= perm.strongest_idempotent_foreign_access(false));
+            }
+            for prot in bool::exhaustive() {
+                if prot {
+                    precondition!(perm.compatible_with_protector());
+                }
+                let access = perm.strongest_idempotent_foreign_access(prot);
+                // We now assert it is idempotent, and never causes UB.
+                // First, if the SIFA includes foreign reads, assert it is idempotent under foreign reads.
+                if access >= IdempotentForeignAccess::Read {
+                    // We use `CousinAccess` here. We could also use `AncestorAccess`, since `transition::perform_access` treats these the same.
+                    // The only place they are treated differently is in protector end accesses, but these are not handled here.
+                    assert_eq!(perm, transition::perform_access(AccessKind::Read, AccessRelatedness::CousinAccess, perm, prot).unwrap());
+                }
+                // Then, if the SIFA includes foreign writes, assert it is idempotent under foreign writes.
+                if access >= IdempotentForeignAccess::Write {
+                    assert_eq!(perm, transition::perform_access(AccessKind::Write, AccessRelatedness::CousinAccess, perm, prot).unwrap());
+                }
+            }
+        }
+    }
+
+    #[test]
     // Check that all transitions are consistent with the order on PermissionPriv,
     // i.e. Reserved -> Active -> Frozen -> Disabled
     fn permissionpriv_partialord_is_reachability() {
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 61b3338e6a2..3f524dc589f 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -21,6 +21,7 @@ use crate::borrow_tracker::tree_borrows::Permission;
 use crate::borrow_tracker::tree_borrows::diagnostics::{
     self, NodeDebugInfo, TbError, TransitionError,
 };
+use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess;
 use crate::borrow_tracker::tree_borrows::perms::PermTransition;
 use crate::borrow_tracker::tree_borrows::unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap};
 use crate::borrow_tracker::{GlobalState, ProtectorKind};
@@ -45,28 +46,28 @@ pub(super) struct LocationState {
     initialized: bool,
     /// This pointer's current permission / future initial permission.
     permission: Permission,
-    /// Strongest foreign access whose effects have already been applied to
-    /// this node and all its children since the last child access.
-    /// This is `None` if the most recent access is a child access,
-    /// `Some(Write)` if at least one foreign write access has been applied
-    /// since the previous child access, and `Some(Read)` if at least one
-    /// foreign read and no foreign write have occurred since the last child access.
-    latest_foreign_access: Option<AccessKind>,
+    /// See `foreign_access_skipping.rs`.
+    /// Stores an idempotent foreign access for this location and its children.
+    /// For correctness, this must not be too strong, and the recorded idempotent foreign access
+    /// of all children must be at least as strong as this. For performance, it should be as strong as possible.
+    idempotent_foreign_access: IdempotentForeignAccess,
 }
 
 impl LocationState {
     /// Constructs a new initial state. It has neither been accessed, nor been subjected
     /// to any foreign access yet.
     /// The permission is not allowed to be `Active`.
-    fn new_uninit(permission: Permission) -> Self {
+    /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs`
+    fn new_uninit(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
         assert!(permission.is_initial() || permission.is_disabled());
-        Self { permission, initialized: false, latest_foreign_access: None }
+        Self { permission, initialized: false, idempotent_foreign_access: sifa }
     }
 
     /// Constructs a new initial state. It has not yet been subjected
     /// to any foreign access. However, it is already marked as having been accessed.
-    fn new_init(permission: Permission) -> Self {
-        Self { permission, initialized: true, latest_foreign_access: None }
+    /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs`
+    fn new_init(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
+        Self { permission, initialized: true, idempotent_foreign_access: sifa }
     }
 
     /// Check if the location has been initialized, i.e. if it has
@@ -143,52 +144,21 @@ impl LocationState {
         }
     }
 
-    // Helper to optimize the tree traversal.
-    // The optimization here consists of observing thanks to the tests
-    // `foreign_read_is_noop_after_foreign_write` and `all_transitions_idempotent`,
-    // that there are actually just three possible sequences of events that can occur
-    // in between two child accesses that produce different results.
-    //
-    // Indeed,
-    // - applying any number of foreign read accesses is the same as applying
-    //   exactly one foreign read,
-    // - applying any number of foreign read or write accesses is the same
-    //   as applying exactly one foreign write.
-    // therefore the three sequences of events that can produce different
-    // outcomes are
-    // - an empty sequence (`self.latest_foreign_access = None`)
-    // - a nonempty read-only sequence (`self.latest_foreign_access = Some(Read)`)
-    // - a nonempty sequence with at least one write (`self.latest_foreign_access = Some(Write)`)
-    //
-    // This function not only determines if skipping the propagation right now
-    // is possible, it also updates the internal state to keep track of whether
-    // the propagation can be skipped next time.
-    // It is a performance loss not to call this function when a foreign access occurs.
-    // FIXME: This optimization is wrong, and is currently disabled (by ignoring the
-    // result returned here). Since we presumably want an optimization like this,
-    // we should add it back. See #3864 for more information.
+    /// Tree traversal optimizations. See `foreign_access_skipping.rs`.
+    /// This checks if such a foreign access can be skipped.
     fn skip_if_known_noop(
         &self,
         access_kind: AccessKind,
         rel_pos: AccessRelatedness,
     ) -> ContinueTraversal {
         if rel_pos.is_foreign() {
-            let new_access_noop = match (self.latest_foreign_access, access_kind) {
-                // Previously applied transition makes the new one a guaranteed
-                // noop in the two following cases:
-                // (1) justified by `foreign_read_is_noop_after_foreign_write`
-                (Some(AccessKind::Write), AccessKind::Read) => true,
-                // (2) justified by `all_transitions_idempotent`
-                (Some(old), new) if old == new => true,
-                // In all other cases there has been a recent enough
-                // child access that the effects of the new foreign access
-                // need to be applied to this subtree.
-                _ => false,
-            };
+            let happening_now = IdempotentForeignAccess::from_foreign(access_kind);
+            let new_access_noop =
+                self.idempotent_foreign_access.can_skip_foreign_access(happening_now);
             if new_access_noop {
-                // Abort traversal if the new transition is indeed guaranteed
+                // Abort traversal if the new access is indeed guaranteed
                 // to be noop.
-                // No need to update `self.latest_foreign_access`,
+                // No need to update `self.idempotent_foreign_access`,
                 // the type of the current streak among nonempty read-only
                 // or nonempty with at least one write has not changed.
                 ContinueTraversal::SkipSelfAndChildren
@@ -207,20 +177,17 @@ impl LocationState {
     }
 
     /// Records a new access, so that future access can potentially be skipped
-    /// by `skip_if_known_noop`.
-    /// The invariants for this function are closely coupled to the function above:
-    /// It MUST be called on child accesses, and on foreign accesses MUST be called
-    /// when `skip_if_know_noop` returns `Recurse`, and MUST NOT be called otherwise.
-    /// FIXME: This optimization is wrong, and is currently disabled (by ignoring the
-    /// result returned here). Since we presumably want an optimization like this,
-    /// we should add it back. See #3864 for more information.
-    #[allow(unused)]
+    /// by `skip_if_known_noop`. This must be called on child accesses, and otherwise
+    /// shoud be called on foreign accesses for increased performance. It should not be called
+    /// when `skip_if_known_noop` indicated skipping, since it then is a no-op.
+    /// See `foreign_access_skipping.rs`
     fn record_new_access(&mut self, access_kind: AccessKind, rel_pos: AccessRelatedness) {
-        if rel_pos.is_foreign() {
-            self.latest_foreign_access = Some(access_kind);
-        } else {
-            self.latest_foreign_access = None;
-        }
+        debug_assert!(matches!(
+            self.skip_if_known_noop(access_kind, rel_pos),
+            ContinueTraversal::Recurse
+        ));
+        self.idempotent_foreign_access
+            .record_new(IdempotentForeignAccess::from_acc_and_rel(access_kind, rel_pos));
     }
 }
 
@@ -277,6 +244,11 @@ pub(super) struct Node {
     /// It is only ever `Disabled` for a tree root, since the root is initialized to `Active` by
     /// its own separate mechanism.
     default_initial_perm: Permission,
+    /// The default initial (strongest) idempotent foreign access.
+    /// This participates in the invariant for `LocationState::idempotent_foreign_access`
+    /// in cases where there is no location state yet. See `foreign_access_skipping.rs`,
+    /// and `LocationState::idempotent_foreign_access` for more information
+    default_initial_idempotent_foreign_access: IdempotentForeignAccess,
     /// Some extra information useful only for debugging purposes
     pub debug_info: NodeDebugInfo,
 }
@@ -430,7 +402,7 @@ where
                 }
                 self.stack.push((
                     child,
-                    AccessRelatedness::DistantAccess,
+                    AccessRelatedness::CousinAccess,
                     RecursionState::BeforeChildren,
                 ));
             }
@@ -591,6 +563,8 @@ impl Tree {
                 parent: None,
                 children: SmallVec::default(),
                 default_initial_perm: root_default_perm,
+                // The root may never be skipped, all accesses will be local.
+                default_initial_idempotent_foreign_access: IdempotentForeignAccess::None,
                 debug_info,
             });
             nodes
@@ -601,7 +575,10 @@ impl Tree {
             // We also ensure that it is initialized, so that no `Active` but
             // not yet initialized nodes exist. Essentially, we pretend there
             // was a write that initialized these to `Active`.
-            perms.insert(root_idx, LocationState::new_init(Permission::new_active()));
+            perms.insert(
+                root_idx,
+                LocationState::new_init(Permission::new_active(), IdempotentForeignAccess::None),
+            );
             RangeMap::new(size, perms)
         };
         Self { root: root_idx, nodes, rperms, tag_mapping }
@@ -617,29 +594,79 @@ impl<'tcx> Tree {
         default_initial_perm: Permission,
         reborrow_range: AllocRange,
         span: Span,
+        prot: bool,
     ) -> InterpResult<'tcx> {
         assert!(!self.tag_mapping.contains_key(&new_tag));
         let idx = self.tag_mapping.insert(new_tag);
         let parent_idx = self.tag_mapping.get(&parent_tag).unwrap();
+        let strongest_idempotent = default_initial_perm.strongest_idempotent_foreign_access(prot);
         // Create the node
         self.nodes.insert(idx, Node {
             tag: new_tag,
             parent: Some(parent_idx),
             children: SmallVec::default(),
             default_initial_perm,
+            default_initial_idempotent_foreign_access: strongest_idempotent,
             debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span),
         });
         // Register new_tag as a child of parent_tag
         self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
         // Initialize perms
-        let perm = LocationState::new_init(default_initial_perm);
+        let perm = LocationState::new_init(default_initial_perm, strongest_idempotent);
         for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
         {
             perms.insert(idx, perm);
         }
+
+        // Inserting the new perms might have broken the SIFA invariant (see `foreign_access_skipping.rs`).
+        // We now weaken the recorded SIFA for our parents, until the invariant is restored.
+        // We could weaken them all to `LocalAccess`, but it is more efficient to compute the SIFA
+        // for the new permission statically, and use that.
+        self.update_last_accessed_after_retag(parent_idx, strongest_idempotent);
+
         interp_ok(())
     }
 
+    /// Restores the SIFA "children are stronger" invariant after a retag.
+    /// See `foreign_access_skipping` and `new_child`.
+    fn update_last_accessed_after_retag(
+        &mut self,
+        mut current: UniIndex,
+        strongest_allowed: IdempotentForeignAccess,
+    ) {
+        // We walk the tree upwards, until the invariant is restored
+        loop {
+            let current_node = self.nodes.get_mut(current).unwrap();
+            // Call `ensure_no_stronger_than` on all SIFAs for this node: the per-location SIFA, as well
+            // as the default SIFA for not-yet-initialized locations.
+            // Record whether we did any change; if not, the invariant is restored and we can stop the traversal.
+            let mut any_change = false;
+            for (_, map) in self.rperms.iter_mut_all() {
+                // Check if this node has a state for this location (or range of locations).
+                if let Some(perm) = map.get_mut(current) {
+                    // Update the per-location SIFA, recording if it changed.
+                    any_change |=
+                        perm.idempotent_foreign_access.ensure_no_stronger_than(strongest_allowed);
+                }
+            }
+            // Now update `default_initial_idempotent_foreign_access`, which stores the default SIFA for not-yet-initialized locations.
+            any_change |= current_node
+                .default_initial_idempotent_foreign_access
+                .ensure_no_stronger_than(strongest_allowed);
+
+            if any_change {
+                let Some(next) = self.nodes.get(current).unwrap().parent else {
+                    // We have arrived at the root.
+                    break;
+                };
+                current = next;
+                continue;
+            } else {
+                break;
+            }
+        }
+    }
+
     /// Deallocation requires
     /// - a pointer that permits write accesses
     /// - the absence of Strong Protectors anywhere in the allocation
@@ -731,13 +758,8 @@ impl<'tcx> Tree {
         let node_skipper = |access_kind: AccessKind, args: &NodeAppArgs<'_>| -> ContinueTraversal {
             let NodeAppArgs { node, perm, rel_pos } = args;
 
-            let old_state = perm
-                .get()
-                .copied()
-                .unwrap_or_else(|| LocationState::new_uninit(node.default_initial_perm));
-            // FIXME: See #3684
-            let _would_skip_if_not_for_fixme = old_state.skip_if_known_noop(access_kind, *rel_pos);
-            ContinueTraversal::Recurse
+            let old_state = perm.get().copied().unwrap_or_else(|| node.default_location_state());
+            old_state.skip_if_known_noop(access_kind, *rel_pos)
         };
         let node_app = |perms_range: Range<u64>,
                         access_kind: AccessKind,
@@ -746,10 +768,12 @@ impl<'tcx> Tree {
          -> Result<(), TransitionError> {
             let NodeAppArgs { node, mut perm, rel_pos } = args;
 
-            let old_state = perm.or_insert(LocationState::new_uninit(node.default_initial_perm));
+            let old_state = perm.or_insert(node.default_location_state());
 
-            // FIXME: See #3684
-            // old_state.record_new_access(access_kind, rel_pos);
+            // Call this function now, which ensures it is only called when
+            // `skip_if_known_noop` returns `Recurse`, due to the contract of
+            // `traverse_this_parents_children_other`.
+            old_state.record_new_access(access_kind, rel_pos);
 
             let protected = global.borrow().protected_tags.contains_key(&node.tag);
             let transition = old_state.perform_access(access_kind, rel_pos, protected)?;
@@ -976,6 +1000,15 @@ impl Tree {
     }
 }
 
+impl Node {
+    pub fn default_location_state(&self) -> LocationState {
+        LocationState::new_uninit(
+            self.default_initial_perm,
+            self.default_initial_idempotent_foreign_access,
+        )
+    }
+}
+
 impl VisitProvenance for Tree {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         // To ensure that the root never gets removed, we visit it
@@ -998,15 +1031,14 @@ pub enum AccessRelatedness {
     AncestorAccess,
     /// The accessed pointer is neither of the above.
     // It's a cousin/uncle/etc., something in a side branch.
-    // FIXME: find a better name ?
-    DistantAccess,
+    CousinAccess,
 }
 
 impl AccessRelatedness {
     /// Check that access is either Ancestor or Distant, i.e. not
     /// a transitive child (initial pointer included).
     pub fn is_foreign(self) -> bool {
-        matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::DistantAccess)
+        matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::CousinAccess)
     }
 
     /// Given the AccessRelatedness for the parent node, compute the AccessRelatedness
@@ -1016,7 +1048,7 @@ impl AccessRelatedness {
         use AccessRelatedness::*;
         match self {
             AncestorAccess | This => AncestorAccess,
-            StrictChildAccess | DistantAccess => DistantAccess,
+            StrictChildAccess | CousinAccess => CousinAccess,
         }
     }
 }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
index 5d51a72852c..a429940748c 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
@@ -10,7 +10,11 @@ impl Exhaustive for LocationState {
     fn exhaustive() -> Box<dyn Iterator<Item = Self>> {
         // We keep `latest_foreign_access` at `None` as that's just a cache.
         Box::new(<(Permission, bool)>::exhaustive().map(|(permission, initialized)| {
-            Self { permission, initialized, latest_foreign_access: None }
+            Self {
+                permission,
+                initialized,
+                idempotent_foreign_access: IdempotentForeignAccess::default(),
+            }
         }))
     }
 }
@@ -260,15 +264,15 @@ mod spurious_read {
             match xy_rel {
                 RelPosXY::MutuallyForeign =>
                     match self {
-                        PtrSelector::X => (This, DistantAccess),
-                        PtrSelector::Y => (DistantAccess, This),
-                        PtrSelector::Other => (DistantAccess, DistantAccess),
+                        PtrSelector::X => (This, CousinAccess),
+                        PtrSelector::Y => (CousinAccess, This),
+                        PtrSelector::Other => (CousinAccess, CousinAccess),
                     },
                 RelPosXY::XChildY =>
                     match self {
                         PtrSelector::X => (This, StrictChildAccess),
                         PtrSelector::Y => (AncestorAccess, This),
-                        PtrSelector::Other => (DistantAccess, DistantAccess),
+                        PtrSelector::Other => (CousinAccess, CousinAccess),
                     },
             }
         }
@@ -598,13 +602,18 @@ mod spurious_read {
         let source = LocStateProtPair {
             xy_rel: RelPosXY::MutuallyForeign,
             x: LocStateProt {
-                state: LocationState::new_init(Permission::new_frozen()),
+                // For the tests, the strongest idempotent foreign access does not matter, so we use `Default::default`
+                state: LocationState::new_init(
+                    Permission::new_frozen(),
+                    IdempotentForeignAccess::default(),
+                ),
                 prot: true,
             },
             y: LocStateProt {
-                state: LocationState::new_uninit(Permission::new_reserved(
-                    /* freeze */ true, /* protected */ true,
-                )),
+                state: LocationState::new_uninit(
+                    Permission::new_reserved(/* freeze */ true, /* protected */ true),
+                    IdempotentForeignAccess::default(),
+                ),
                 prot: true,
             },
         };
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index f86d1eb1dcb..4cdc9348dc9 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -108,19 +108,19 @@ pub(super) struct ThreadClockSet {
     fence_acquire: VClock,
 
     /// The last timestamp of happens-before relations that
-    /// have been released by this thread by a fence.
+    /// have been released by this thread by a release fence.
     fence_release: VClock,
 
-    /// Timestamps of the last SC fence performed by each
-    /// thread, updated when this thread performs an SC fence
-    pub(super) fence_seqcst: VClock,
-
     /// Timestamps of the last SC write performed by each
-    /// thread, updated when this thread performs an SC fence
+    /// thread, updated when this thread performs an SC fence.
+    /// This is never acquired into the thread's clock, it
+    /// just limits which old writes can be seen in weak memory emulation.
     pub(super) write_seqcst: VClock,
 
     /// Timestamps of the last SC fence performed by each
-    /// thread, updated when this thread performs an SC read
+    /// thread, updated when this thread performs an SC read.
+    /// This is never acquired into the thread's clock, it
+    /// just limits which old writes can be seen in weak memory emulation.
     pub(super) read_seqcst: VClock,
 }
 
@@ -256,6 +256,106 @@ enum AccessType {
     AtomicRmw,
 }
 
+/// Per-byte vector clock metadata for data-race detection.
+#[derive(Clone, PartialEq, Eq, Debug)]
+struct MemoryCellClocks {
+    /// The vector-clock timestamp and the thread that did the last non-atomic write. We don't need
+    /// a full `VClock` here, it's always a single thread and nothing synchronizes, so the effective
+    /// clock is all-0 except for the thread that did the write.
+    write: (VectorIdx, VTimestamp),
+
+    /// The type of operation that the write index represents,
+    /// either newly allocated memory, a non-atomic write or
+    /// a deallocation of memory.
+    write_type: NaWriteType,
+
+    /// The vector-clock of all non-atomic reads that happened since the last non-atomic write
+    /// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to
+    /// zero on each write operation.
+    read: VClock,
+
+    /// Atomic access, acquire, release sequence tracking clocks.
+    /// For non-atomic memory this value is set to None.
+    /// For atomic memory, each byte carries this information.
+    atomic_ops: Option<Box<AtomicMemoryCellClocks>>,
+}
+
+/// Extra metadata associated with a thread.
+#[derive(Debug, Clone, Default)]
+struct ThreadExtraState {
+    /// The current vector index in use by the
+    /// thread currently, this is set to None
+    /// after the vector index has been re-used
+    /// and hence the value will never need to be
+    /// read during data-race reporting.
+    vector_index: Option<VectorIdx>,
+
+    /// Thread termination vector clock, this
+    /// is set on thread termination and is used
+    /// for joining on threads since the vector_index
+    /// may be re-used when the join operation occurs.
+    termination_vector_clock: Option<VClock>,
+}
+
+/// Global data-race detection state, contains the currently
+/// executing thread as well as the vector-clocks associated
+/// with each of the threads.
+// FIXME: it is probably better to have one large RefCell, than to have so many small ones.
+#[derive(Debug, Clone)]
+pub struct GlobalState {
+    /// Set to true once the first additional
+    /// thread has launched, due to the dependency
+    /// between before and after a thread launch.
+    /// Any data-races must be recorded after this
+    /// so concurrent execution can ignore recording
+    /// any data-races.
+    multi_threaded: Cell<bool>,
+
+    /// A flag to mark we are currently performing
+    /// a data race free action (such as atomic access)
+    /// to suppress the race detector
+    ongoing_action_data_race_free: Cell<bool>,
+
+    /// Mapping of a vector index to a known set of thread
+    /// clocks, this is not directly mapping from a thread id
+    /// since it may refer to multiple threads.
+    vector_clocks: RefCell<IndexVec<VectorIdx, ThreadClockSet>>,
+
+    /// Mapping of a given vector index to the current thread
+    /// that the execution is representing, this may change
+    /// if a vector index is re-assigned to a new thread.
+    vector_info: RefCell<IndexVec<VectorIdx, ThreadId>>,
+
+    /// The mapping of a given thread to associated thread metadata.
+    thread_info: RefCell<IndexVec<ThreadId, ThreadExtraState>>,
+
+    /// Potential vector indices that could be re-used on thread creation
+    /// values are inserted here on after the thread has terminated and
+    /// been joined with, and hence may potentially become free
+    /// for use as the index for a new thread.
+    /// Elements in this set may still require the vector index to
+    /// report data-races, and can only be re-used after all
+    /// active vector-clocks catch up with the threads timestamp.
+    reuse_candidates: RefCell<FxHashSet<VectorIdx>>,
+
+    /// We make SC fences act like RMWs on a global location.
+    /// To implement that, they all release and acquire into this clock.
+    last_sc_fence: RefCell<VClock>,
+
+    /// The timestamp of last SC write performed by each thread.
+    /// Threads only update their own index here!
+    last_sc_write_per_thread: RefCell<VClock>,
+
+    /// Track when an outdated (weak memory) load happens.
+    pub track_outdated_loads: bool,
+}
+
+impl VisitProvenance for GlobalState {
+    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
+        // We don't have any tags.
+    }
+}
+
 impl AccessType {
     fn description(self, ty: Option<Ty<'_>>, size: Option<Size>) -> String {
         let mut msg = String::new();
@@ -309,30 +409,6 @@ impl AccessType {
     }
 }
 
-/// Per-byte vector clock metadata for data-race detection.
-#[derive(Clone, PartialEq, Eq, Debug)]
-struct MemoryCellClocks {
-    /// The vector-clock timestamp and the thread that did the last non-atomic write. We don't need
-    /// a full `VClock` here, it's always a single thread and nothing synchronizes, so the effective
-    /// clock is all-0 except for the thread that did the write.
-    write: (VectorIdx, VTimestamp),
-
-    /// The type of operation that the write index represents,
-    /// either newly allocated memory, a non-atomic write or
-    /// a deallocation of memory.
-    write_type: NaWriteType,
-
-    /// The vector-clock of all non-atomic reads that happened since the last non-atomic write
-    /// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to
-    /// zero on each write operation.
-    read: VClock,
-
-    /// Atomic access, acquire, release sequence tracking clocks.
-    /// For non-atomic memory this value is set to None.
-    /// For atomic memory, each byte carries this information.
-    atomic_ops: Option<Box<AtomicMemoryCellClocks>>,
-}
-
 impl AtomicMemoryCellClocks {
     fn new(size: Size) -> Self {
         AtomicMemoryCellClocks {
@@ -798,15 +874,27 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
                         // Either Acquire | AcqRel | SeqCst
                         clocks.apply_acquire_fence();
                     }
+                    if atomic == AtomicFenceOrd::SeqCst {
+                        // Behave like an RMW on the global fence location. This takes full care of
+                        // all the SC fence requirements, including C++17 §32.4 [atomics.order]
+                        // paragraph 6 (which would limit what future reads can see). It also rules
+                        // out many legal behaviors, but we don't currently have a model that would
+                        // be more precise.
+                        // Also see the second bullet on page 10 of
+                        // <https://www.cs.tau.ac.il/~orilahav/papers/popl21_robustness.pdf>.
+                        let mut sc_fence_clock = data_race.last_sc_fence.borrow_mut();
+                        sc_fence_clock.join(&clocks.clock);
+                        clocks.clock.join(&sc_fence_clock);
+                        // Also establish some sort of order with the last SC write that happened, globally
+                        // (but this is only respected by future reads).
+                        clocks.write_seqcst.join(&data_race.last_sc_write_per_thread.borrow());
+                    }
+                    // The release fence is last, since both of the above could alter our clock,
+                    // which should be part of what is being released.
                     if atomic != AtomicFenceOrd::Acquire {
                         // Either Release | AcqRel | SeqCst
                         clocks.apply_release_fence();
                     }
-                    if atomic == AtomicFenceOrd::SeqCst {
-                        data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index);
-                        clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow());
-                        clocks.write_seqcst.join(&data_race.last_sc_write.borrow());
-                    }
 
                     // Increment timestamp in case of release semantics.
                     interp_ok(atomic != AtomicFenceOrd::Acquire)
@@ -1463,80 +1551,6 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     }
 }
 
-/// Extra metadata associated with a thread.
-#[derive(Debug, Clone, Default)]
-struct ThreadExtraState {
-    /// The current vector index in use by the
-    /// thread currently, this is set to None
-    /// after the vector index has been re-used
-    /// and hence the value will never need to be
-    /// read during data-race reporting.
-    vector_index: Option<VectorIdx>,
-
-    /// Thread termination vector clock, this
-    /// is set on thread termination and is used
-    /// for joining on threads since the vector_index
-    /// may be re-used when the join operation occurs.
-    termination_vector_clock: Option<VClock>,
-}
-
-/// Global data-race detection state, contains the currently
-/// executing thread as well as the vector-clocks associated
-/// with each of the threads.
-// FIXME: it is probably better to have one large RefCell, than to have so many small ones.
-#[derive(Debug, Clone)]
-pub struct GlobalState {
-    /// Set to true once the first additional
-    /// thread has launched, due to the dependency
-    /// between before and after a thread launch.
-    /// Any data-races must be recorded after this
-    /// so concurrent execution can ignore recording
-    /// any data-races.
-    multi_threaded: Cell<bool>,
-
-    /// A flag to mark we are currently performing
-    /// a data race free action (such as atomic access)
-    /// to suppress the race detector
-    ongoing_action_data_race_free: Cell<bool>,
-
-    /// Mapping of a vector index to a known set of thread
-    /// clocks, this is not directly mapping from a thread id
-    /// since it may refer to multiple threads.
-    vector_clocks: RefCell<IndexVec<VectorIdx, ThreadClockSet>>,
-
-    /// Mapping of a given vector index to the current thread
-    /// that the execution is representing, this may change
-    /// if a vector index is re-assigned to a new thread.
-    vector_info: RefCell<IndexVec<VectorIdx, ThreadId>>,
-
-    /// The mapping of a given thread to associated thread metadata.
-    thread_info: RefCell<IndexVec<ThreadId, ThreadExtraState>>,
-
-    /// Potential vector indices that could be re-used on thread creation
-    /// values are inserted here on after the thread has terminated and
-    /// been joined with, and hence may potentially become free
-    /// for use as the index for a new thread.
-    /// Elements in this set may still require the vector index to
-    /// report data-races, and can only be re-used after all
-    /// active vector-clocks catch up with the threads timestamp.
-    reuse_candidates: RefCell<FxHashSet<VectorIdx>>,
-
-    /// The timestamp of last SC fence performed by each thread
-    last_sc_fence: RefCell<VClock>,
-
-    /// The timestamp of last SC write performed by each thread
-    last_sc_write: RefCell<VClock>,
-
-    /// Track when an outdated (weak memory) load happens.
-    pub track_outdated_loads: bool,
-}
-
-impl VisitProvenance for GlobalState {
-    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
-        // We don't have any tags.
-    }
-}
-
 impl GlobalState {
     /// Create a new global state, setup with just thread-id=0
     /// advanced to timestamp = 1.
@@ -1549,7 +1563,7 @@ impl GlobalState {
             thread_info: RefCell::new(IndexVec::new()),
             reuse_candidates: RefCell::new(FxHashSet::default()),
             last_sc_fence: RefCell::new(VClock::default()),
-            last_sc_write: RefCell::new(VClock::default()),
+            last_sc_write_per_thread: RefCell::new(VClock::default()),
             track_outdated_loads: config.track_outdated_loads,
         };
 
@@ -1851,7 +1865,7 @@ impl GlobalState {
     // SC ATOMIC STORE rule in the paper.
     pub(super) fn sc_write(&self, thread_mgr: &ThreadManager<'_>) {
         let (index, clocks) = self.active_thread_state(thread_mgr);
-        self.last_sc_write.borrow_mut().set_at_index(&clocks.clock, index);
+        self.last_sc_write_per_thread.borrow_mut().set_at_index(&clocks.clock, index);
     }
 
     // SC ATOMIC READ rule in the paper.
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index c610f1999f7..1a3e9614f8a 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -11,10 +11,17 @@
 //! This implementation is not fully correct under the revised C++20 model and may generate behaviours C++20
 //! disallows (<https://github.com/rust-lang/miri/issues/2301>).
 //!
-//! A modification is made to the paper's model to partially address C++20 changes.
-//! Specifically, if an SC load reads from an atomic store of any ordering, then a later SC load cannot read from
-//! an earlier store in the location's modification order. This is to prevent creating a backwards S edge from the second
-//! load to the first, as a result of C++20's coherence-ordered before rules.
+//! Modifications are made to the paper's model to address C++20 changes:
+//! - If an SC load reads from an atomic store of any ordering, then a later SC load cannot read
+//!   from an earlier store in the location's modification order. This is to prevent creating a
+//!   backwards S edge from the second load to the first, as a result of C++20's coherence-ordered
+//!   before rules. (This seems to rule out behaviors that were actually permitted by the RC11 model
+//!   that C++20 intended to copy (<https://plv.mpi-sws.org/scfix/paper.pdf>); a change was
+//!   introduced when translating the math to English. According to Viktor Vafeiadis, this
+//!   difference is harmless. So we stick to what the standard says, and allow fewer behaviors.)
+//! - SC fences are treated like AcqRel RMWs to a global clock, to ensure they induce enough
+//!   synchronization with the surrounding accesses. This rules out legal behavior, but it is really
+//!   hard to be more precise here.
 //!
 //! Rust follows the C++20 memory model (except for the Consume ordering and some operations not performable through C++'s
 //! `std::atomic<T>` API). It is therefore possible for this implementation to generate behaviours never observable when the
@@ -138,6 +145,7 @@ struct StoreElement {
 
     /// The timestamp of the storing thread when it performed the store
     timestamp: VTimestamp,
+
     /// The value of this store. `None` means uninitialized.
     // FIXME: Currently, we cannot represent partial initialization.
     val: Option<Scalar>,
@@ -335,11 +343,6 @@ impl<'tcx> StoreBuffer {
                     // then we cannot read-from anything earlier in modification order.
                     // C++20 §6.9.2.2 [intro.races] paragraph 16
                     false
-                } else if store_elem.timestamp <= clocks.fence_seqcst[store_elem.store_index] {
-                    // The current load, which may be sequenced-after an SC fence, cannot read-before
-                    // the last store sequenced-before an SC fence in another thread.
-                    // C++17 §32.4 [atomics.order] paragraph 6
-                    false
                 } else if store_elem.timestamp <= clocks.write_seqcst[store_elem.store_index]
                     && store_elem.is_seqcst
                 {
@@ -356,9 +359,9 @@ impl<'tcx> StoreBuffer {
                     false
                 } else if is_seqcst && store_elem.load_info.borrow().sc_loaded {
                     // The current SC load cannot read-before a store that an earlier SC load has observed.
-                    // See https://github.com/rust-lang/miri/issues/2301#issuecomment-1222720427
+                    // See https://github.com/rust-lang/miri/issues/2301#issuecomment-1222720427.
                     // Consequences of C++20 §31.4 [atomics.order] paragraph 3.1, 3.3 (coherence-ordered before)
-                    // and 4.1 (coherence-ordered before between SC makes global total order S)
+                    // and 4.1 (coherence-ordered before between SC makes global total order S).
                     false
                 } else {
                     true
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index 075b6f35e0e..54bdd3f02c2 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -1,4 +1,5 @@
 use either::Either;
+use rand::Rng;
 use rustc_abi::{Endian, HasDataLayout};
 use rustc_apfloat::{Float, Round};
 use rustc_middle::ty::FloatTy;
@@ -286,7 +287,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     this.write_scalar(val, &dest)?;
                 }
             }
-            "fma" => {
+            "fma" | "relaxed_fma" => {
                 let [a, b, c] = check_arg_count(args)?;
                 let (a, a_len) = this.project_to_simd(a)?;
                 let (b, b_len) = this.project_to_simd(b)?;
@@ -303,6 +304,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     let c = this.read_scalar(&this.project_index(&c, i)?)?;
                     let dest = this.project_index(&dest, i)?;
 
+                    let fuse: bool = intrinsic_name == "fma" || this.machine.rng.get_mut().gen();
+
                     // Works for f32 and f64.
                     // FIXME: using host floats to work around https://github.com/rust-lang/miri/issues/2468.
                     let ty::Float(float_ty) = dest.layout.ty.kind() else {
@@ -314,7 +317,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                             let a = a.to_f32()?;
                             let b = b.to_f32()?;
                             let c = c.to_f32()?;
-                            let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                            let res = if fuse {
+                                a.to_host().mul_add(b.to_host(), c.to_host()).to_soft()
+                            } else {
+                                ((a * b).value + c).value
+                            };
                             let res = this.adjust_nan(res, &[a, b, c]);
                             Scalar::from(res)
                         }
@@ -322,7 +329,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                             let a = a.to_f64()?;
                             let b = b.to_f64()?;
                             let c = c.to_f64()?;
-                            let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                            let res = if fuse {
+                                a.to_host().mul_add(b.to_host(), c.to_host()).to_soft()
+                            } else {
+                                ((a * b).value + c).value
+                            };
                             let res = this.adjust_nan(res, &[a, b, c]);
                             Scalar::from(res)
                         }
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 814dc6d2b01..7cc22f83a24 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -270,6 +270,9 @@ impl interpret::Provenance for Provenance {
     /// We use absolute addresses in the `offset` of a `StrictPointer`.
     const OFFSET_IS_ADDR: bool = true;
 
+    /// Miri implements wildcard provenance.
+    const WILDCARD: Option<Self> = Some(Provenance::Wildcard);
+
     fn get_alloc_id(self) -> Option<AllocId> {
         match self {
             Provenance::Concrete { alloc_id, .. } => Some(alloc_id),
@@ -1242,8 +1245,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     /// Called on `ptr as usize` casts.
     /// (Actually computing the resulting `usize` doesn't need machine help,
     /// that's just `Scalar::try_to_int`.)
-    fn expose_ptr(ecx: &mut InterpCx<'tcx, Self>, ptr: StrictPointer) -> InterpResult<'tcx> {
-        match ptr.provenance {
+    fn expose_provenance(
+        ecx: &InterpCx<'tcx, Self>,
+        provenance: Self::Provenance,
+    ) -> InterpResult<'tcx> {
+        match provenance {
             Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 64bd546458d..c7b399228bf 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -1,5 +1,4 @@
 use rustc_abi::{ExternAbi, Size};
-use rustc_ast::ast::Mutability;
 use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::{BytePos, Loc, Symbol, hygiene};
@@ -179,14 +178,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         match flags {
             0 => {
-                // These are "mutable" allocations as we consider them to be owned by the callee.
-                let name_alloc =
-                    this.allocate_str(&name, MiriMemoryKind::Rust.into(), Mutability::Mut)?;
-                let filename_alloc =
-                    this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut)?;
-
-                this.write_immediate(name_alloc.to_ref(this), &this.project_field(dest, 0)?)?;
-                this.write_immediate(filename_alloc.to_ref(this), &this.project_field(dest, 1)?)?;
+                throw_unsup_format!("miri_resolve_frame: v0 is not supported any more");
             }
             1 => {
                 this.write_scalar(
diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs
new file mode 100644
index 00000000000..f673b834be2
--- /dev/null
+++ b/src/tools/miri/src/shims/files.rs
@@ -0,0 +1,411 @@
+use std::any::Any;
+use std::collections::BTreeMap;
+use std::io::{IsTerminal, Read, SeekFrom, Write};
+use std::ops::Deref;
+use std::rc::{Rc, Weak};
+use std::{fs, io};
+
+use rustc_abi::Size;
+
+use crate::shims::unix::UnixFileDescription;
+use crate::*;
+
+/// Represents an open file description.
+pub trait FileDescription: std::fmt::Debug + Any {
+    fn name(&self) -> &'static str;
+
+    /// Reads as much as possible into the given buffer `ptr`.
+    /// `len` indicates how many bytes we should try to read.
+    /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error.
+    fn read<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        _communicate_allowed: bool,
+        _ptr: Pointer,
+        _len: usize,
+        _dest: &MPlaceTy<'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("cannot read from {}", self.name());
+    }
+
+    /// Writes as much as possible from the given buffer `ptr`.
+    /// `len` indicates how many bytes we should try to write.
+    /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error.
+    fn write<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        _communicate_allowed: bool,
+        _ptr: Pointer,
+        _len: usize,
+        _dest: &MPlaceTy<'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("cannot write to {}", self.name());
+    }
+
+    /// Seeks to the given offset (which can be relative to the beginning, end, or current position).
+    /// Returns the new position from the start of the stream.
+    fn seek<'tcx>(
+        &self,
+        _communicate_allowed: bool,
+        _offset: SeekFrom,
+    ) -> InterpResult<'tcx, io::Result<u64>> {
+        throw_unsup_format!("cannot seek on {}", self.name());
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        throw_unsup_format!("cannot close {}", self.name());
+    }
+
+    fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result<fs::Metadata>> {
+        throw_unsup_format!("obtaining metadata is only supported on file-backed file descriptors");
+    }
+
+    fn is_tty(&self, _communicate_allowed: bool) -> bool {
+        // Most FDs are not tty's and the consequence of a wrong `false` are minor,
+        // so we use a default impl here.
+        false
+    }
+
+    fn as_unix(&self) -> &dyn UnixFileDescription {
+        panic!("Not a unix file descriptor: {}", self.name());
+    }
+}
+
+impl dyn FileDescription {
+    #[inline(always)]
+    pub fn downcast<T: Any>(&self) -> Option<&T> {
+        (self as &dyn Any).downcast_ref()
+    }
+}
+
+impl FileDescription for io::Stdin {
+    fn name(&self) -> &'static str {
+        "stdin"
+    }
+
+    fn read<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        communicate_allowed: bool,
+        ptr: Pointer,
+        len: usize,
+        dest: &MPlaceTy<'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let mut bytes = vec![0; len];
+        if !communicate_allowed {
+            // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
+            helpers::isolation_abort_error("`read` from stdin")?;
+        }
+        let result = Read::read(&mut { self }, &mut bytes);
+        match result {
+            Ok(read_size) => ecx.return_read_success(ptr, &bytes, read_size, dest),
+            Err(e) => ecx.set_last_error_and_return(e, dest),
+        }
+    }
+
+    fn is_tty(&self, communicate_allowed: bool) -> bool {
+        communicate_allowed && self.is_terminal()
+    }
+}
+
+impl FileDescription for io::Stdout {
+    fn name(&self) -> &'static str {
+        "stdout"
+    }
+
+    fn write<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        _communicate_allowed: bool,
+        ptr: Pointer,
+        len: usize,
+        dest: &MPlaceTy<'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
+        // We allow writing to stderr even with isolation enabled.
+        let result = Write::write(&mut { self }, bytes);
+        // Stdout is buffered, flush to make sure it appears on the
+        // screen.  This is the write() syscall of the interpreted
+        // program, we want it to correspond to a write() syscall on
+        // the host -- there is no good in adding extra buffering
+        // here.
+        io::stdout().flush().unwrap();
+        match result {
+            Ok(write_size) => ecx.return_write_success(write_size, dest),
+            Err(e) => ecx.set_last_error_and_return(e, dest),
+        }
+    }
+
+    fn is_tty(&self, communicate_allowed: bool) -> bool {
+        communicate_allowed && self.is_terminal()
+    }
+}
+
+impl FileDescription for io::Stderr {
+    fn name(&self) -> &'static str {
+        "stderr"
+    }
+
+    fn write<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        _communicate_allowed: bool,
+        ptr: Pointer,
+        len: usize,
+        dest: &MPlaceTy<'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
+        // We allow writing to stderr even with isolation enabled.
+        // No need to flush, stderr is not buffered.
+        let result = Write::write(&mut { self }, bytes);
+        match result {
+            Ok(write_size) => ecx.return_write_success(write_size, dest),
+            Err(e) => ecx.set_last_error_and_return(e, dest),
+        }
+    }
+
+    fn is_tty(&self, communicate_allowed: bool) -> bool {
+        communicate_allowed && self.is_terminal()
+    }
+}
+
+/// Like /dev/null
+#[derive(Debug)]
+pub struct NullOutput;
+
+impl FileDescription for NullOutput {
+    fn name(&self) -> &'static str {
+        "stderr and stdout"
+    }
+
+    fn write<'tcx>(
+        &self,
+        _self_ref: &FileDescriptionRef,
+        _communicate_allowed: bool,
+        _ptr: Pointer,
+        len: usize,
+        dest: &MPlaceTy<'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx> {
+        // We just don't write anything, but report to the user that we did.
+        ecx.return_write_success(len, dest)
+    }
+}
+
+/// Structure contains both the file description and its unique identifier.
+#[derive(Clone, Debug)]
+pub struct FileDescWithId<T: FileDescription + ?Sized> {
+    id: FdId,
+    file_description: Box<T>,
+}
+
+#[derive(Clone, Debug)]
+pub struct FileDescriptionRef(Rc<FileDescWithId<dyn FileDescription>>);
+
+impl Deref for FileDescriptionRef {
+    type Target = dyn FileDescription;
+
+    fn deref(&self) -> &Self::Target {
+        &*self.0.file_description
+    }
+}
+
+impl FileDescriptionRef {
+    fn new(fd: impl FileDescription, id: FdId) -> Self {
+        FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) }))
+    }
+
+    pub fn close<'tcx>(
+        self,
+        communicate_allowed: bool,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        // Destroy this `Rc` using `into_inner` so we can call `close` instead of
+        // implicitly running the destructor of the file description.
+        let id = self.get_id();
+        match Rc::into_inner(self.0) {
+            Some(fd) => {
+                // Remove entry from the global epoll_event_interest table.
+                ecx.machine.epoll_interests.remove(id);
+
+                fd.file_description.close(communicate_allowed, ecx)
+            }
+            None => interp_ok(Ok(())),
+        }
+    }
+
+    pub fn downgrade(&self) -> WeakFileDescriptionRef {
+        WeakFileDescriptionRef { weak_ref: Rc::downgrade(&self.0) }
+    }
+
+    pub fn get_id(&self) -> FdId {
+        self.0.id
+    }
+}
+
+/// Holds a weak reference to the actual file description.
+#[derive(Clone, Debug, Default)]
+pub struct WeakFileDescriptionRef {
+    weak_ref: Weak<FileDescWithId<dyn FileDescription>>,
+}
+
+impl WeakFileDescriptionRef {
+    pub fn upgrade(&self) -> Option<FileDescriptionRef> {
+        if let Some(file_desc_with_id) = self.weak_ref.upgrade() {
+            return Some(FileDescriptionRef(file_desc_with_id));
+        }
+        None
+    }
+}
+
+impl VisitProvenance for WeakFileDescriptionRef {
+    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
+        // A weak reference can never be the only reference to some pointer or place.
+        // Since the actual file description is tracked by strong ref somewhere,
+        // it is ok to make this a NOP operation.
+    }
+}
+
+/// A unique id for file descriptions. While we could use the address, considering that
+/// is definitely unique, the address would expose interpreter internal state when used
+/// for sorting things. So instead we generate a unique id per file description is the name
+/// for all `dup`licates and is never reused.
+#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
+pub struct FdId(usize);
+
+/// The file descriptor table
+#[derive(Debug)]
+pub struct FdTable {
+    pub fds: BTreeMap<i32, FileDescriptionRef>,
+    /// Unique identifier for file description, used to differentiate between various file description.
+    next_file_description_id: FdId,
+}
+
+impl VisitProvenance for FdTable {
+    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
+        // All our FileDescription instances do not have any tags.
+    }
+}
+
+impl FdTable {
+    fn new() -> Self {
+        FdTable { fds: BTreeMap::new(), next_file_description_id: FdId(0) }
+    }
+    pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable {
+        let mut fds = FdTable::new();
+        fds.insert_new(io::stdin());
+        if mute_stdout_stderr {
+            assert_eq!(fds.insert_new(NullOutput), 1);
+            assert_eq!(fds.insert_new(NullOutput), 2);
+        } else {
+            assert_eq!(fds.insert_new(io::stdout()), 1);
+            assert_eq!(fds.insert_new(io::stderr()), 2);
+        }
+        fds
+    }
+
+    pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef {
+        let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id);
+        self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1));
+        file_handle
+    }
+
+    /// Insert a new file description to the FdTable.
+    pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 {
+        let fd_ref = self.new_ref(fd);
+        self.insert(fd_ref)
+    }
+
+    pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 {
+        self.insert_with_min_num(fd_ref, 0)
+    }
+
+    /// Insert a file description, giving it a file descriptor that is at least `min_fd_num`.
+    pub fn insert_with_min_num(&mut self, file_handle: FileDescriptionRef, min_fd_num: i32) -> i32 {
+        // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
+        // between used FDs, the find_map combinator will return it. If the first such unused FD
+        // is after all other used FDs, the find_map combinator will return None, and we will use
+        // the FD following the greatest FD thus far.
+        let candidate_new_fd =
+            self.fds.range(min_fd_num..).zip(min_fd_num..).find_map(|((fd_num, _fd), counter)| {
+                if *fd_num != counter {
+                    // There was a gap in the fds stored, return the first unused one
+                    // (note that this relies on BTreeMap iterating in key order)
+                    Some(counter)
+                } else {
+                    // This fd is used, keep going
+                    None
+                }
+            });
+        let new_fd_num = candidate_new_fd.unwrap_or_else(|| {
+            // find_map ran out of BTreeMap entries before finding a free fd, use one plus the
+            // maximum fd in the map
+            self.fds.last_key_value().map(|(fd_num, _)| fd_num.strict_add(1)).unwrap_or(min_fd_num)
+        });
+
+        self.fds.try_insert(new_fd_num, file_handle).unwrap();
+        new_fd_num
+    }
+
+    pub fn get(&self, fd_num: i32) -> Option<FileDescriptionRef> {
+        let fd = self.fds.get(&fd_num)?;
+        Some(fd.clone())
+    }
+
+    pub fn remove(&mut self, fd_num: i32) -> Option<FileDescriptionRef> {
+        self.fds.remove(&fd_num)
+    }
+
+    pub fn is_fd_num(&self, fd_num: i32) -> bool {
+        self.fds.contains_key(&fd_num)
+    }
+}
+
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    /// Helper to implement `FileDescription::read`:
+    /// This is only used when `read` is successful.
+    /// `actual_read_size` should be the return value of some underlying `read` call that used
+    /// `bytes` as its output buffer.
+    /// The length of `bytes` must not exceed either the host's or the target's `isize`.
+    /// `bytes` is written to `buf` and the size is written to `dest`.
+    fn return_read_success(
+        &mut self,
+        buf: Pointer,
+        bytes: &[u8],
+        actual_read_size: usize,
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        // If reading to `bytes` did not fail, we write those bytes to the buffer.
+        // Crucially, if fewer than `bytes.len()` bytes were read, only write
+        // that much into the output buffer!
+        this.write_bytes_ptr(buf, bytes[..actual_read_size].iter().copied())?;
+
+        // The actual read size is always less than what got originally requested so this cannot fail.
+        this.write_int(u64::try_from(actual_read_size).unwrap(), dest)?;
+        interp_ok(())
+    }
+
+    /// Helper to implement `FileDescription::write`:
+    /// This function is only used when `write` is successful, and writes `actual_write_size` to `dest`
+    fn return_write_success(
+        &mut self,
+        actual_write_size: usize,
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        // The actual write size is always less than what got originally requested so this cannot fail.
+        this.write_int(u64::try_from(actual_write_size).unwrap(), dest)?;
+        interp_ok(())
+    }
+}
diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs
index 0cbb4850b7f..acf3f74a93d 100644
--- a/src/tools/miri/src/shims/io_error.rs
+++ b/src/tools/miri/src/shims/io_error.rs
@@ -44,7 +44,7 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
         ("ECONNREFUSED", ConnectionRefused),
         ("ECONNRESET", ConnectionReset),
         ("EDEADLK", Deadlock),
-        ("EDQUOT", FilesystemQuotaExceeded),
+        ("EDQUOT", QuotaExceeded),
         ("EEXIST", AlreadyExists),
         ("EFBIG", FileTooLarge),
         ("EHOSTUNREACH", HostUnreachable),
@@ -82,11 +82,72 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
 // <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/windows/mod.rs>.
 const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
     use std::io::ErrorKind::*;
-    // FIXME: this is still incomplete.
+    // It's common for multiple error codes to map to the same io::ErrorKind. We have all for the
+    // forwards mapping; only the first one will be used for the backwards mapping.
+    // Slightly arbitrarily, we prefer non-WSA and the most generic sounding variant for backwards
+    // mapping.
     &[
-        ("ERROR_ACCESS_DENIED", PermissionDenied),
-        ("ERROR_FILE_NOT_FOUND", NotFound),
+        ("WSAEADDRINUSE", AddrInUse),
+        ("WSAEADDRNOTAVAIL", AddrNotAvailable),
+        ("ERROR_ALREADY_EXISTS", AlreadyExists),
+        ("ERROR_FILE_EXISTS", AlreadyExists),
+        ("ERROR_NO_DATA", BrokenPipe),
+        ("WSAECONNABORTED", ConnectionAborted),
+        ("WSAECONNREFUSED", ConnectionRefused),
+        ("WSAECONNRESET", ConnectionReset),
+        ("ERROR_NOT_SAME_DEVICE", CrossesDevices),
+        ("ERROR_POSSIBLE_DEADLOCK", Deadlock),
+        ("ERROR_DIR_NOT_EMPTY", DirectoryNotEmpty),
+        ("ERROR_CANT_RESOLVE_FILENAME", FilesystemLoop),
+        ("ERROR_DISK_QUOTA_EXCEEDED", QuotaExceeded),
+        ("WSAEDQUOT", QuotaExceeded),
+        ("ERROR_FILE_TOO_LARGE", FileTooLarge),
+        ("ERROR_HOST_UNREACHABLE", HostUnreachable),
+        ("WSAEHOSTUNREACH", HostUnreachable),
+        ("ERROR_INVALID_NAME", InvalidFilename),
+        ("ERROR_BAD_PATHNAME", InvalidFilename),
+        ("ERROR_FILENAME_EXCED_RANGE", InvalidFilename),
         ("ERROR_INVALID_PARAMETER", InvalidInput),
+        ("WSAEINVAL", InvalidInput),
+        ("ERROR_DIRECTORY_NOT_SUPPORTED", IsADirectory),
+        ("WSAENETDOWN", NetworkDown),
+        ("ERROR_NETWORK_UNREACHABLE", NetworkUnreachable),
+        ("WSAENETUNREACH", NetworkUnreachable),
+        ("ERROR_DIRECTORY", NotADirectory),
+        ("WSAENOTCONN", NotConnected),
+        ("ERROR_FILE_NOT_FOUND", NotFound),
+        ("ERROR_PATH_NOT_FOUND", NotFound),
+        ("ERROR_INVALID_DRIVE", NotFound),
+        ("ERROR_BAD_NETPATH", NotFound),
+        ("ERROR_BAD_NET_NAME", NotFound),
+        ("ERROR_SEEK_ON_DEVICE", NotSeekable),
+        ("ERROR_NOT_ENOUGH_MEMORY", OutOfMemory),
+        ("ERROR_OUTOFMEMORY", OutOfMemory),
+        ("ERROR_ACCESS_DENIED", PermissionDenied),
+        ("WSAEACCES", PermissionDenied),
+        ("ERROR_WRITE_PROTECT", ReadOnlyFilesystem),
+        ("ERROR_BUSY", ResourceBusy),
+        ("ERROR_DISK_FULL", StorageFull),
+        ("ERROR_HANDLE_DISK_FULL", StorageFull),
+        ("WAIT_TIMEOUT", TimedOut),
+        ("WSAETIMEDOUT", TimedOut),
+        ("ERROR_DRIVER_CANCEL_TIMEOUT", TimedOut),
+        ("ERROR_OPERATION_ABORTED", TimedOut),
+        ("ERROR_SERVICE_REQUEST_TIMEOUT", TimedOut),
+        ("ERROR_COUNTER_TIMEOUT", TimedOut),
+        ("ERROR_TIMEOUT", TimedOut),
+        ("ERROR_RESOURCE_CALL_TIMED_OUT", TimedOut),
+        ("ERROR_CTX_MODEM_RESPONSE_TIMEOUT", TimedOut),
+        ("ERROR_CTX_CLIENT_QUERY_TIMEOUT", TimedOut),
+        ("FRS_ERR_SYSVOL_POPULATE_TIMEOUT", TimedOut),
+        ("ERROR_DS_TIMELIMIT_EXCEEDED", TimedOut),
+        ("DNS_ERROR_RECORD_TIMED_OUT", TimedOut),
+        ("ERROR_IPSEC_IKE_TIMED_OUT", TimedOut),
+        ("ERROR_RUNLEVEL_SWITCH_TIMEOUT", TimedOut),
+        ("ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT", TimedOut),
+        ("ERROR_TOO_MANY_LINKS", TooManyLinks),
+        ("ERROR_CALL_NOT_IMPLEMENTED", Unsupported),
+        ("WSAEWOULDBLOCK", WouldBlock),
     ]
 };
 
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index b9317ac1a15..61681edcf76 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -2,6 +2,7 @@
 
 mod alloc;
 mod backtrace;
+mod files;
 #[cfg(unix)]
 mod native_lib;
 mod unix;
@@ -18,7 +19,8 @@ pub mod panic;
 pub mod time;
 pub mod tls;
 
-pub use self::unix::{DirTable, EpollInterestTable, FdTable};
+pub use self::files::FdTable;
+pub use self::unix::{DirTable, EpollInterestTable};
 
 /// What needs to be done after emulating an item (a shim or an intrinsic) is done.
 pub enum EmulateItemResult {
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index e7a4251242e..f18d0236774 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -3,7 +3,8 @@ use std::ops::Deref;
 
 use libffi::high::call as ffi;
 use libffi::low::CodePtr;
-use rustc_abi::{BackendRepr, HasDataLayout};
+use rustc_abi::{BackendRepr, HasDataLayout, Size};
+use rustc_middle::mir::interpret::Pointer;
 use rustc_middle::ty::{self as ty, IntTy, UintTy};
 use rustc_span::Symbol;
 
@@ -75,6 +76,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) };
                 return interp_ok(ImmTy::uninit(dest.layout));
             }
+            ty::RawPtr(..) => {
+                let x = unsafe { ffi::call::<*const ()>(ptr, libffi_args.as_slice()) };
+                let ptr = Pointer::new(Provenance::Wildcard, Size::from_bytes(x.addr()));
+                Scalar::from_pointer(ptr, this)
+            }
             _ => throw_unsup_format!("unsupported return type for native call: {:?}", link_name),
         };
         interp_ok(ImmTy::from_scalar(scalar, dest.layout))
@@ -152,9 +158,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
                 throw_unsup_format!("only scalar argument types are support for native calls")
             }
-            libffi_args.push(imm_to_carg(this.read_immediate(arg)?, this)?);
+            let imm = this.read_immediate(arg)?;
+            libffi_args.push(imm_to_carg(&imm, this)?);
+            // If we are passing a pointer, prepare the memory it points to.
+            if matches!(arg.layout.ty.kind(), ty::RawPtr(..)) {
+                let ptr = imm.to_scalar().to_pointer(this)?;
+                let Some(prov) = ptr.provenance else {
+                    // Pointer without provenance may not access any memory.
+                    continue;
+                };
+                // We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance.
+                let Some(alloc_id) = prov.get_alloc_id() else {
+                    // Wildcard pointer, whatever it points to must be already exposed.
+                    continue;
+                };
+                this.prepare_for_native_call(alloc_id, prov)?;
+            }
         }
 
+        // FIXME: In the future, we should also call `prepare_for_native_call` on all previously
+        // exposed allocations, since C may access any of them.
+
         // Convert them to `libffi::high::Arg` type.
         let libffi_args = libffi_args
             .iter()
@@ -220,7 +244,7 @@ impl<'a> CArg {
 
 /// Extract the scalar value from the result of reading a scalar from the machine,
 /// and convert it to a `CArg`.
-fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> {
+fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> {
     interp_ok(match v.layout.ty.kind() {
         // If the primitive provided can be converted to a type matching the type pattern
         // then create a `CArg` of this primitive value with the corresponding `CArg` constructor.
@@ -238,18 +262,10 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
         ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?),
         ty::Uint(UintTy::Usize) =>
             CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()),
-        ty::RawPtr(_, mutability) => {
-            // Arbitrary mutable pointer accesses are not currently supported in Miri.
-            if mutability.is_mut() {
-                throw_unsup_format!(
-                    "unsupported mutable pointer type for native call: {}",
-                    v.layout.ty
-                );
-            } else {
-                let s = v.to_scalar().to_pointer(cx)?.addr();
-                // This relies on the `expose_provenance` in `addr_from_alloc_id`.
-                CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
-            }
+        ty::RawPtr(..) => {
+            let s = v.to_scalar().to_pointer(cx)?.addr();
+            // This relies on the `expose_provenance` in `addr_from_alloc_id`.
+            CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
         }
         _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
     })
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 722c3a2f0c5..93479540009 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -12,7 +12,6 @@
 //!   metadata we remembered when pushing said frame.
 
 use rustc_abi::ExternAbi;
-use rustc_ast::Mutability;
 use rustc_middle::{mir, ty};
 use rustc_target::spec::PanicStrategy;
 
@@ -161,7 +160,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let this = self.eval_context_mut();
 
         // First arg: message.
-        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?;
+        let msg = this.allocate_str_dedup(msg)?;
 
         // Call the lang item.
         let panic = this.tcx.lang_items().panic_fn().unwrap();
@@ -180,7 +179,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let this = self.eval_context_mut();
 
         // First arg: message.
-        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?;
+        let msg = this.allocate_str_dedup(msg)?;
 
         // Call the lang item.
         let panic = this.tcx.lang_items().panic_nounwind().unwrap();
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 80ad40e1624..f9003885450 100644
--- a/src/tools/miri/src/shims/unix/android/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs
@@ -2,7 +2,9 @@ use rustc_abi::ExternAbi;
 use rustc_span::Symbol;
 
 use crate::shims::unix::android::thread::prctl;
-use crate::shims::unix::linux::syscall::syscall;
+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 {
@@ -20,6 +22,31 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
+            // epoll, eventfd
+            "epoll_create1" => {
+                let [flag] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_create1(flag)?;
+                this.write_scalar(result, dest)?;
+            }
+            "epoll_ctl" => {
+                let [epfd, op, fd, event] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_ctl(epfd, op, fd, event)?;
+                this.write_scalar(result, dest)?;
+            }
+            "epoll_wait" => {
+                let [epfd, events, maxevents, timeout] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
+            }
+            "eventfd" => {
+                let [val, flag] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.eventfd(val, flag)?;
+                this.write_scalar(result, dest)?;
+            }
+
             // Miscellaneous
             "__errno" => {
                 let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 27bdd508f77..e5dead1a263 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -1,16 +1,14 @@
 //! General management of file descriptors, and support for
 //! standard file descriptors (stdin/stdout/stderr).
 
-use std::any::Any;
-use std::collections::BTreeMap;
-use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write};
-use std::ops::Deref;
-use std::rc::{Rc, Weak};
+use std::io;
+use std::io::ErrorKind;
 
 use rustc_abi::Size;
 
 use crate::helpers::check_min_arg_count;
-use crate::shims::unix::linux::epoll::EpollReadyEvents;
+use crate::shims::files::FileDescription;
+use crate::shims::unix::linux_like::epoll::EpollReadyEvents;
 use crate::shims::unix::*;
 use crate::*;
 
@@ -21,40 +19,8 @@ pub(crate) enum FlockOp {
     Unlock,
 }
 
-/// Represents an open file description.
-pub trait FileDescription: std::fmt::Debug + Any {
-    fn name(&self) -> &'static str;
-
-    /// Reads as much as possible into the given buffer `ptr`.
-    /// `len` indicates how many bytes we should try to read.
-    /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error.
-    fn read<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        _communicate_allowed: bool,
-        _ptr: Pointer,
-        _len: usize,
-        _dest: &MPlaceTy<'tcx>,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        throw_unsup_format!("cannot read from {}", self.name());
-    }
-
-    /// Writes as much as possible from the given buffer `ptr`.
-    /// `len` indicates how many bytes we should try to write.
-    /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error.
-    fn write<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        _communicate_allowed: bool,
-        _ptr: Pointer,
-        _len: usize,
-        _dest: &MPlaceTy<'tcx>,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        throw_unsup_format!("cannot write to {}", self.name());
-    }
-
+/// Represents unix-specific file descriptions.
+pub trait UnixFileDescription: FileDescription {
     /// Reads as much as possible into the given buffer `ptr` from a given offset.
     /// `len` indicates how many bytes we should try to read.
     /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error.
@@ -86,24 +52,6 @@ pub trait FileDescription: std::fmt::Debug + Any {
         throw_unsup_format!("cannot pwrite to {}", self.name());
     }
 
-    /// Seeks to the given offset (which can be relative to the beginning, end, or current position).
-    /// Returns the new position from the start of the stream.
-    fn seek<'tcx>(
-        &self,
-        _communicate_allowed: bool,
-        _offset: SeekFrom,
-    ) -> InterpResult<'tcx, io::Result<u64>> {
-        throw_unsup_format!("cannot seek on {}", self.name());
-    }
-
-    fn close<'tcx>(
-        self: Box<Self>,
-        _communicate_allowed: bool,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx, io::Result<()>> {
-        throw_unsup_format!("cannot close {}", self.name());
-    }
-
     fn flock<'tcx>(
         &self,
         _communicate_allowed: bool,
@@ -112,311 +60,12 @@ pub trait FileDescription: std::fmt::Debug + Any {
         throw_unsup_format!("cannot flock {}", self.name());
     }
 
-    fn is_tty(&self, _communicate_allowed: bool) -> bool {
-        // Most FDs are not tty's and the consequence of a wrong `false` are minor,
-        // so we use a default impl here.
-        false
-    }
-
     /// Check the readiness of file description.
     fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
         throw_unsup_format!("{}: epoll does not support this file description", self.name());
     }
 }
 
-impl dyn FileDescription {
-    #[inline(always)]
-    pub fn downcast<T: Any>(&self) -> Option<&T> {
-        (self as &dyn Any).downcast_ref()
-    }
-}
-
-impl FileDescription for io::Stdin {
-    fn name(&self) -> &'static str {
-        "stdin"
-    }
-
-    fn read<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        communicate_allowed: bool,
-        ptr: Pointer,
-        len: usize,
-        dest: &MPlaceTy<'tcx>,
-        ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        let mut bytes = vec![0; len];
-        if !communicate_allowed {
-            // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
-            helpers::isolation_abort_error("`read` from stdin")?;
-        }
-        let result = Read::read(&mut { self }, &mut bytes);
-        match result {
-            Ok(read_size) => ecx.return_read_success(ptr, &bytes, read_size, dest),
-            Err(e) => ecx.set_last_error_and_return(e, dest),
-        }
-    }
-
-    fn is_tty(&self, communicate_allowed: bool) -> bool {
-        communicate_allowed && self.is_terminal()
-    }
-}
-
-impl FileDescription for io::Stdout {
-    fn name(&self) -> &'static str {
-        "stdout"
-    }
-
-    fn write<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        _communicate_allowed: bool,
-        ptr: Pointer,
-        len: usize,
-        dest: &MPlaceTy<'tcx>,
-        ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
-        // We allow writing to stderr even with isolation enabled.
-        let result = Write::write(&mut { self }, bytes);
-        // Stdout is buffered, flush to make sure it appears on the
-        // screen.  This is the write() syscall of the interpreted
-        // program, we want it to correspond to a write() syscall on
-        // the host -- there is no good in adding extra buffering
-        // here.
-        io::stdout().flush().unwrap();
-        match result {
-            Ok(write_size) => ecx.return_write_success(write_size, dest),
-            Err(e) => ecx.set_last_error_and_return(e, dest),
-        }
-    }
-
-    fn is_tty(&self, communicate_allowed: bool) -> bool {
-        communicate_allowed && self.is_terminal()
-    }
-}
-
-impl FileDescription for io::Stderr {
-    fn name(&self) -> &'static str {
-        "stderr"
-    }
-
-    fn write<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        _communicate_allowed: bool,
-        ptr: Pointer,
-        len: usize,
-        dest: &MPlaceTy<'tcx>,
-        ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
-        // We allow writing to stderr even with isolation enabled.
-        // No need to flush, stderr is not buffered.
-        let result = Write::write(&mut { self }, bytes);
-        match result {
-            Ok(write_size) => ecx.return_write_success(write_size, dest),
-            Err(e) => ecx.set_last_error_and_return(e, dest),
-        }
-    }
-
-    fn is_tty(&self, communicate_allowed: bool) -> bool {
-        communicate_allowed && self.is_terminal()
-    }
-}
-
-/// Like /dev/null
-#[derive(Debug)]
-pub struct NullOutput;
-
-impl FileDescription for NullOutput {
-    fn name(&self) -> &'static str {
-        "stderr and stdout"
-    }
-
-    fn write<'tcx>(
-        &self,
-        _self_ref: &FileDescriptionRef,
-        _communicate_allowed: bool,
-        _ptr: Pointer,
-        len: usize,
-        dest: &MPlaceTy<'tcx>,
-        ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx> {
-        // We just don't write anything, but report to the user that we did.
-        ecx.return_write_success(len, dest)
-    }
-}
-
-/// Structure contains both the file description and its unique identifier.
-#[derive(Clone, Debug)]
-pub struct FileDescWithId<T: FileDescription + ?Sized> {
-    id: FdId,
-    file_description: Box<T>,
-}
-
-#[derive(Clone, Debug)]
-pub struct FileDescriptionRef(Rc<FileDescWithId<dyn FileDescription>>);
-
-impl Deref for FileDescriptionRef {
-    type Target = dyn FileDescription;
-
-    fn deref(&self) -> &Self::Target {
-        &*self.0.file_description
-    }
-}
-
-impl FileDescriptionRef {
-    fn new(fd: impl FileDescription, id: FdId) -> Self {
-        FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) }))
-    }
-
-    pub fn close<'tcx>(
-        self,
-        communicate_allowed: bool,
-        ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx, io::Result<()>> {
-        // Destroy this `Rc` using `into_inner` so we can call `close` instead of
-        // implicitly running the destructor of the file description.
-        let id = self.get_id();
-        match Rc::into_inner(self.0) {
-            Some(fd) => {
-                // Remove entry from the global epoll_event_interest table.
-                ecx.machine.epoll_interests.remove(id);
-
-                fd.file_description.close(communicate_allowed, ecx)
-            }
-            None => interp_ok(Ok(())),
-        }
-    }
-
-    pub fn downgrade(&self) -> WeakFileDescriptionRef {
-        WeakFileDescriptionRef { weak_ref: Rc::downgrade(&self.0) }
-    }
-
-    pub fn get_id(&self) -> FdId {
-        self.0.id
-    }
-}
-
-/// Holds a weak reference to the actual file description.
-#[derive(Clone, Debug, Default)]
-pub struct WeakFileDescriptionRef {
-    weak_ref: Weak<FileDescWithId<dyn FileDescription>>,
-}
-
-impl WeakFileDescriptionRef {
-    pub fn upgrade(&self) -> Option<FileDescriptionRef> {
-        if let Some(file_desc_with_id) = self.weak_ref.upgrade() {
-            return Some(FileDescriptionRef(file_desc_with_id));
-        }
-        None
-    }
-}
-
-impl VisitProvenance for WeakFileDescriptionRef {
-    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
-        // A weak reference can never be the only reference to some pointer or place.
-        // Since the actual file description is tracked by strong ref somewhere,
-        // it is ok to make this a NOP operation.
-    }
-}
-
-/// A unique id for file descriptions. While we could use the address, considering that
-/// is definitely unique, the address would expose interpreter internal state when used
-/// for sorting things. So instead we generate a unique id per file description that stays
-/// the same even if a file descriptor is duplicated and gets a new integer file descriptor.
-#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
-pub struct FdId(usize);
-
-/// The file descriptor table
-#[derive(Debug)]
-pub struct FdTable {
-    pub fds: BTreeMap<i32, FileDescriptionRef>,
-    /// Unique identifier for file description, used to differentiate between various file description.
-    next_file_description_id: FdId,
-}
-
-impl VisitProvenance for FdTable {
-    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
-        // All our FileDescription instances do not have any tags.
-    }
-}
-
-impl FdTable {
-    fn new() -> Self {
-        FdTable { fds: BTreeMap::new(), next_file_description_id: FdId(0) }
-    }
-    pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable {
-        let mut fds = FdTable::new();
-        fds.insert_new(io::stdin());
-        if mute_stdout_stderr {
-            assert_eq!(fds.insert_new(NullOutput), 1);
-            assert_eq!(fds.insert_new(NullOutput), 2);
-        } else {
-            assert_eq!(fds.insert_new(io::stdout()), 1);
-            assert_eq!(fds.insert_new(io::stderr()), 2);
-        }
-        fds
-    }
-
-    pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef {
-        let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id);
-        self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1));
-        file_handle
-    }
-
-    /// Insert a new file description to the FdTable.
-    pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 {
-        let fd_ref = self.new_ref(fd);
-        self.insert(fd_ref)
-    }
-
-    pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 {
-        self.insert_with_min_num(fd_ref, 0)
-    }
-
-    /// Insert a file description, giving it a file descriptor that is at least `min_fd_num`.
-    fn insert_with_min_num(&mut self, file_handle: FileDescriptionRef, min_fd_num: i32) -> i32 {
-        // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
-        // between used FDs, the find_map combinator will return it. If the first such unused FD
-        // is after all other used FDs, the find_map combinator will return None, and we will use
-        // the FD following the greatest FD thus far.
-        let candidate_new_fd =
-            self.fds.range(min_fd_num..).zip(min_fd_num..).find_map(|((fd_num, _fd), counter)| {
-                if *fd_num != counter {
-                    // There was a gap in the fds stored, return the first unused one
-                    // (note that this relies on BTreeMap iterating in key order)
-                    Some(counter)
-                } else {
-                    // This fd is used, keep going
-                    None
-                }
-            });
-        let new_fd_num = candidate_new_fd.unwrap_or_else(|| {
-            // find_map ran out of BTreeMap entries before finding a free fd, use one plus the
-            // maximum fd in the map
-            self.fds.last_key_value().map(|(fd_num, _)| fd_num.strict_add(1)).unwrap_or(min_fd_num)
-        });
-
-        self.fds.try_insert(new_fd_num, file_handle).unwrap();
-        new_fd_num
-    }
-
-    pub fn get(&self, fd_num: i32) -> Option<FileDescriptionRef> {
-        let fd = self.fds.get(&fd_num)?;
-        Some(fd.clone())
-    }
-
-    pub fn remove(&mut self, fd_num: i32) -> Option<FileDescriptionRef> {
-        self.fds.remove(&fd_num)
-    }
-
-    pub fn is_fd_num(&self, fd_num: i32) -> bool {
-        self.fds.contains_key(&fd_num)
-    }
-}
-
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn dup(&mut self, old_fd_num: i32) -> InterpResult<'tcx, Scalar> {
@@ -472,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             throw_unsup_format!("unsupported flags {:#x}", op);
         };
 
-        let result = fd.flock(this.machine.communicate(), parsed_op)?;
+        let result = fd.as_unix().flock(this.machine.communicate(), parsed_op)?;
         drop(fd);
         // return `0` if flock is successful
         let result = result.map(|()| 0i32);
@@ -602,7 +251,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let Ok(offset) = u64::try_from(offset) else {
                     return this.set_last_error_and_return(LibcError("EINVAL"), dest);
                 };
-                fd.pread(communicate, offset, buf, count, dest, this)?
+                fd.as_unix().pread(communicate, offset, buf, count, dest, this)?
             }
         };
         interp_ok(())
@@ -642,46 +291,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let Ok(offset) = u64::try_from(offset) else {
                     return this.set_last_error_and_return(LibcError("EINVAL"), dest);
                 };
-                fd.pwrite(communicate, buf, count, offset, dest, this)?
+                fd.as_unix().pwrite(communicate, buf, count, offset, dest, this)?
             }
         };
         interp_ok(())
     }
-
-    /// Helper to implement `FileDescription::read`:
-    /// This is only used when `read` is successful.
-    /// `actual_read_size` should be the return value of some underlying `read` call that used
-    /// `bytes` as its output buffer.
-    /// The length of `bytes` must not exceed either the host's or the target's `isize`.
-    /// `bytes` is written to `buf` and the size is written to `dest`.
-    fn return_read_success(
-        &mut self,
-        buf: Pointer,
-        bytes: &[u8],
-        actual_read_size: usize,
-        dest: &MPlaceTy<'tcx>,
-    ) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
-        // If reading to `bytes` did not fail, we write those bytes to the buffer.
-        // Crucially, if fewer than `bytes.len()` bytes were read, only write
-        // that much into the output buffer!
-        this.write_bytes_ptr(buf, bytes[..actual_read_size].iter().copied())?;
-
-        // The actual read size is always less than what got originally requested so this cannot fail.
-        this.write_int(u64::try_from(actual_read_size).unwrap(), dest)?;
-        interp_ok(())
-    }
-
-    /// Helper to implement `FileDescription::write`:
-    /// This function is only used when `write` is successful, and writes `actual_write_size` to `dest`
-    fn return_write_success(
-        &mut self,
-        actual_write_size: usize,
-        dest: &MPlaceTy<'tcx>,
-    ) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
-        // The actual write size is always less than what got originally requested so this cannot fail.
-        this.write_int(u64::try_from(actual_write_size).unwrap(), dest)?;
-        interp_ok(())
-    }
 }
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 55202a08149..88ec32808b1 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -39,6 +39,64 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    // Querying system information
+    fn sysconf(&mut self, val: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
+        let this = self.eval_context_mut();
+
+        let name = this.read_scalar(val)?.to_i32()?;
+        // FIXME: Which of these are POSIX, and which are GNU/Linux?
+        // At least the names seem to all also exist on macOS.
+        let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[
+            ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
+            ("_SC_PAGE_SIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
+            ("_SC_NPROCESSORS_CONF", |this| {
+                Scalar::from_int(this.machine.num_cpus, this.pointer_size())
+            }),
+            ("_SC_NPROCESSORS_ONLN", |this| {
+                Scalar::from_int(this.machine.num_cpus, this.pointer_size())
+            }),
+            // 512 seems to be a reasonable default. The value is not critical, in
+            // the sense that getpwuid_r takes and checks the buffer length.
+            ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())),
+            // Miri doesn't have a fixed limit on FDs, but we may be limited in terms of how
+            // many *host* FDs we can open. Just use some arbitrary, pretty big value;
+            // this can be adjusted if it causes problems.
+            // The spec imposes a minimum of `_POSIX_OPEN_MAX` (20).
+            ("_SC_OPEN_MAX", |this| Scalar::from_int(2_i32.pow(16), this.pointer_size())),
+        ];
+        for &(sysconf_name, value) in sysconfs {
+            let sysconf_name = this.eval_libc_i32(sysconf_name);
+            if sysconf_name == name {
+                return interp_ok(value(this));
+            }
+        }
+        throw_unsup_format!("unimplemented sysconf name: {}", name)
+    }
+
+    fn strerror_r(
+        &mut self,
+        errnum: &OpTy<'tcx>,
+        buf: &OpTy<'tcx>,
+        buflen: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
+        let this = self.eval_context_mut();
+
+        let errnum = this.read_scalar(errnum)?;
+        let buf = this.read_pointer(buf)?;
+        let buflen = this.read_target_usize(buflen)?;
+        let error = this.try_errnum_to_io_error(errnum)?;
+        let formatted = match error {
+            Some(err) => format!("{err}"),
+            None => format!("<unknown errnum in strerror_r: {errnum}>"),
+        };
+        let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
+        if complete {
+            interp_ok(Scalar::from_i32(0))
+        } else {
+            interp_ok(Scalar::from_i32(this.eval_libc_i32("ERANGE")))
+        }
+    }
+
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
@@ -84,6 +142,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(result, dest)?;
             }
 
+            "sysconf" => {
+                let [val] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.sysconf(val)?;
+                this.write_scalar(result, dest)?;
+            }
+
             // File descriptors
             "read" => {
                 let [fd, buf, count] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
@@ -393,35 +458,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
 
-            // Querying system information
-            "sysconf" => {
-                let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let name = this.read_scalar(name)?.to_i32()?;
-                // FIXME: Which of these are POSIX, and which are GNU/Linux?
-                // At least the names seem to all also exist on macOS.
-                let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[
-                    ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
-                    ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
-                    ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
-                    // 512 seems to be a reasonable default. The value is not critical, in
-                    // the sense that getpwuid_r takes and checks the buffer length.
-                    ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size()))
-                ];
-                let mut result = None;
-                for &(sysconf_name, value) in sysconfs {
-                    let sysconf_name = this.eval_libc_i32(sysconf_name);
-                    if sysconf_name == name {
-                        result = Some(value(this));
-                        break;
-                    }
-                }
-                if let Some(result) = result {
-                    this.write_scalar(result, dest)?;
-                } else {
-                    throw_unsup_format!("unimplemented sysconf name: {}", name)
-                }
-            }
-
             // Thread-local storage
             "pthread_key_create" => {
                 let [key, dtor] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
@@ -724,21 +760,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // We do not support forking, so there is nothing to do here.
                 this.write_null(dest)?;
             }
-            "strerror_r" | "__xpg_strerror_r" => {
-                let [errnum, buf, buflen] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let errnum = this.read_scalar(errnum)?;
-                let buf = this.read_pointer(buf)?;
-                let buflen = this.read_target_usize(buflen)?;
-
-                let error = this.try_errnum_to_io_error(errnum)?;
-                let formatted = match error {
-                    Some(err) => format!("{err}"),
-                    None => format!("<unknown errnum in strerror_r: {errnum}>"),
-                };
-                let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
-                let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE") };
-                this.write_int(ret, dest)?;
-            }
             "getentropy" => {
                 // This function is non-standard but exists with the same signature and behavior on
                 // Linux, macOS, FreeBSD and Solaris/Illumos.
@@ -766,6 +787,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     this.write_null(dest)?;
                 }
             }
+
+            "strerror_r" => {
+                let [errnum, buf, buflen] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.strerror_r(errnum, buf, buflen)?;
+                this.write_scalar(result, dest)?;
+            }
+
             "getrandom" => {
                 // This function is non-standard but exists with the same signature and behavior on
                 // Linux, FreeBSD and Solaris/Illumos.
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 1346d8de7ea..0c9bc005ece 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -53,19 +53,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             "stat" | "stat@FBSD_1.0" => {
                 let [path, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_stat(path, buf)?;
+                let result = this.macos_fbsd_solaris_stat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "lstat" | "lstat@FBSD_1.0" => {
                 let [path, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_lstat(path, buf)?;
+                let result = this.macos_fbsd_solaris_lstat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "fstat" | "fstat@FBSD_1.0" => {
                 let [fd, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_fstat(fd, buf)?;
+                let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "readdir_r" | "readdir_r@FBSD_1.0" => {
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 091def7ac65..b41a4d2246f 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -2,7 +2,8 @@
 
 use std::borrow::Cow;
 use std::fs::{
-    DirBuilder, File, FileType, OpenOptions, ReadDir, read_dir, remove_dir, remove_file, rename,
+    DirBuilder, File, FileType, Metadata, OpenOptions, ReadDir, read_dir, remove_dir, remove_file,
+    rename,
 };
 use std::io::{self, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write};
 use std::path::{Path, PathBuf};
@@ -11,12 +12,11 @@ use std::time::SystemTime;
 use rustc_abi::Size;
 use rustc_data_structures::fx::FxHashMap;
 
-use self::fd::FlockOp;
 use self::shims::time::system_time_to_duration;
 use crate::helpers::check_min_arg_count;
+use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef};
 use crate::shims::os_str::bytes_to_os_str;
-use crate::shims::unix::fd::FileDescriptionRef;
-use crate::shims::unix::*;
+use crate::shims::unix::fd::{FlockOp, UnixFileDescription};
 use crate::*;
 
 #[derive(Debug)]
@@ -66,6 +66,55 @@ impl FileDescription for FileHandle {
         }
     }
 
+    fn seek<'tcx>(
+        &self,
+        communicate_allowed: bool,
+        offset: SeekFrom,
+    ) -> InterpResult<'tcx, io::Result<u64>> {
+        assert!(communicate_allowed, "isolation should have prevented even opening a file");
+        interp_ok((&mut &self.file).seek(offset))
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        communicate_allowed: bool,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        assert!(communicate_allowed, "isolation should have prevented even opening a file");
+        // We sync the file if it was opened in a mode different than read-only.
+        if self.writable {
+            // `File::sync_all` does the checks that are done when closing a file. We do this to
+            // to handle possible errors correctly.
+            let result = self.file.sync_all();
+            // Now we actually close the file and return the result.
+            drop(*self);
+            interp_ok(result)
+        } else {
+            // We drop the file, this closes it but ignores any errors
+            // produced when closing it. This is done because
+            // `File::sync_all` cannot be done over files like
+            // `/dev/urandom` which are read-only. Check
+            // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439
+            // for a deeper discussion.
+            drop(*self);
+            interp_ok(Ok(()))
+        }
+    }
+
+    fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result<Metadata>> {
+        interp_ok(self.file.metadata())
+    }
+
+    fn is_tty(&self, communicate_allowed: bool) -> bool {
+        communicate_allowed && self.file.is_terminal()
+    }
+
+    fn as_unix(&self) -> &dyn UnixFileDescription {
+        self
+    }
+}
+
+impl UnixFileDescription for FileHandle {
     fn pread<'tcx>(
         &self,
         communicate_allowed: bool,
@@ -128,41 +177,6 @@ impl FileDescription for FileHandle {
         }
     }
 
-    fn seek<'tcx>(
-        &self,
-        communicate_allowed: bool,
-        offset: SeekFrom,
-    ) -> InterpResult<'tcx, io::Result<u64>> {
-        assert!(communicate_allowed, "isolation should have prevented even opening a file");
-        interp_ok((&mut &self.file).seek(offset))
-    }
-
-    fn close<'tcx>(
-        self: Box<Self>,
-        communicate_allowed: bool,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx, io::Result<()>> {
-        assert!(communicate_allowed, "isolation should have prevented even opening a file");
-        // We sync the file if it was opened in a mode different than read-only.
-        if self.writable {
-            // `File::sync_all` does the checks that are done when closing a file. We do this to
-            // to handle possible errors correctly.
-            let result = self.file.sync_all();
-            // Now we actually close the file and return the result.
-            drop(*self);
-            interp_ok(result)
-        } else {
-            // We drop the file, this closes it but ignores any errors
-            // produced when closing it. This is done because
-            // `File::sync_all` cannot be done over files like
-            // `/dev/urandom` which are read-only. Check
-            // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439
-            // for a deeper discussion.
-            drop(*self);
-            interp_ok(Ok(()))
-        }
-    }
-
     fn flock<'tcx>(
         &self,
         communicate_allowed: bool,
@@ -257,55 +271,63 @@ impl FileDescription for FileHandle {
             compile_error!("flock is supported only on UNIX and Windows hosts");
         }
     }
-
-    fn is_tty(&self, communicate_allowed: bool) -> bool {
-        communicate_allowed && self.file.is_terminal()
-    }
 }
 
 impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {}
 trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn macos_stat_write_buf(
+    fn macos_fbsd_solaris_write_buf(
         &mut self,
         metadata: FileMetadata,
         buf_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let mode: u16 = metadata.mode.to_u16()?;
-
         let (access_sec, access_nsec) = metadata.accessed.unwrap_or((0, 0));
         let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0));
         let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0));
+        let mode = metadata.mode.to_uint(this.libc_ty_layout("mode_t").size)?;
 
         let buf = this.deref_pointer_as(buf_op, this.libc_ty_layout("stat"))?;
-
         this.write_int_fields_named(
             &[
                 ("st_dev", 0),
-                ("st_mode", mode.into()),
+                ("st_mode", mode.try_into().unwrap()),
                 ("st_nlink", 0),
                 ("st_ino", 0),
                 ("st_uid", 0),
                 ("st_gid", 0),
                 ("st_rdev", 0),
                 ("st_atime", access_sec.into()),
-                ("st_atime_nsec", access_nsec.into()),
                 ("st_mtime", modified_sec.into()),
-                ("st_mtime_nsec", modified_nsec.into()),
                 ("st_ctime", 0),
-                ("st_ctime_nsec", 0),
-                ("st_birthtime", created_sec.into()),
-                ("st_birthtime_nsec", created_nsec.into()),
                 ("st_size", metadata.size.into()),
                 ("st_blocks", 0),
                 ("st_blksize", 0),
-                ("st_flags", 0),
-                ("st_gen", 0),
             ],
             &buf,
         )?;
 
+        if matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
+            this.write_int_fields_named(
+                &[
+                    ("st_atime_nsec", access_nsec.into()),
+                    ("st_mtime_nsec", modified_nsec.into()),
+                    ("st_ctime_nsec", 0),
+                    ("st_birthtime", created_sec.into()),
+                    ("st_birthtime_nsec", created_nsec.into()),
+                    ("st_flags", 0),
+                    ("st_gen", 0),
+                ],
+                &buf,
+            )?;
+        }
+
+        if matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") {
+            // FIXME: write st_fstype field once libc is updated.
+            // https://github.com/rust-lang/libc/pull/4145
+            //this.write_int_fields_named(&[("st_fstype", 0)], &buf)?;
+        }
+
         interp_ok(0)
     }
 
@@ -648,15 +670,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
     }
 
-    fn macos_fbsd_stat(
+    fn macos_fbsd_solaris_stat(
         &mut self,
         path_op: &OpTy<'tcx>,
         buf_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
-            panic!("`macos_fbsd_stat` should not be called on {}", this.tcx.sess.target.os);
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") {
+            panic!("`macos_fbsd_solaris_stat` should not be called on {}", this.tcx.sess.target.os);
         }
 
         let path_scalar = this.read_pointer(path_op)?;
@@ -674,19 +696,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             Err(err) => return this.set_last_error_and_return_i32(err),
         };
 
-        interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
+        interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?))
     }
 
     // `lstat` is used to get symlink metadata.
-    fn macos_fbsd_lstat(
+    fn macos_fbsd_solaris_lstat(
         &mut self,
         path_op: &OpTy<'tcx>,
         buf_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
-            panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os);
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") {
+            panic!(
+                "`macos_fbsd_solaris_lstat` should not be called on {}",
+                this.tcx.sess.target.os
+            );
         }
 
         let path_scalar = this.read_pointer(path_op)?;
@@ -703,18 +728,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             Err(err) => return this.set_last_error_and_return_i32(err),
         };
 
-        interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
+        interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?))
     }
 
-    fn macos_fbsd_fstat(
+    fn macos_fbsd_solaris_fstat(
         &mut self,
         fd_op: &OpTy<'tcx>,
         buf_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
-            panic!("`macos_fbsd_fstat` should not be called on {}", this.tcx.sess.target.os);
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") {
+            panic!(
+                "`macos_fbsd_solaris_fstat` should not be called on {}",
+                this.tcx.sess.target.os
+            );
         }
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -730,7 +758,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             Ok(metadata) => metadata,
             Err(err) => return this.set_last_error_and_return_i32(err),
         };
-        interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
+        interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?))
     }
 
     fn linux_statx(
@@ -1675,16 +1703,7 @@ impl FileMetadata {
             return interp_ok(Err(LibcError("EBADF")));
         };
 
-        let file = &fd
-            .downcast::<FileHandle>()
-            .ok_or_else(|| {
-                err_unsup_format!(
-                    "obtaining metadata is only supported on file-backed file descriptors"
-                )
-            })?
-            .file;
-
-        let metadata = file.metadata();
+        let metadata = fd.metadata()?;
         drop(fd);
         FileMetadata::from_meta(ecx, metadata)
     }
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 85f0d6e1330..bc3619090c0 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -1,11 +1,12 @@
 use rustc_abi::ExternAbi;
 use rustc_span::Symbol;
 
-use self::shims::unix::linux::epoll::EvalContextExt as _;
-use self::shims::unix::linux::eventfd::EvalContextExt as _;
 use self::shims::unix::linux::mem::EvalContextExt as _;
-use self::shims::unix::linux::syscall::syscall;
+use self::shims::unix::linux_like::epoll::EvalContextExt as _;
+use self::shims::unix::linux_like::eventfd::EvalContextExt as _;
+use self::shims::unix::linux_like::syscall::syscall;
 use crate::machine::{SIGRTMAX, SIGRTMIN};
+use crate::shims::unix::foreign_items::EvalContextExt as _;
 use crate::shims::unix::*;
 use crate::*;
 
@@ -143,6 +144,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let ptr = this.mremap(old_address, old_size, new_size, flags)?;
                 this.write_scalar(ptr, dest)?;
             }
+            "__xpg_strerror_r" => {
+                let [errnum, buf, buflen] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.strerror_r(errnum, buf, buflen)?;
+                this.write_scalar(result, dest)?;
+            }
             "__errno_location" => {
                 let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
                 let errno_place = this.last_error_place()?;
diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs
index 159e5aca031..c10dc52cb28 100644
--- a/src/tools/miri/src/shims/unix/linux/mod.rs
+++ b/src/tools/miri/src/shims/unix/linux/mod.rs
@@ -1,6 +1,2 @@
-pub mod epoll;
-pub mod eventfd;
 pub mod foreign_items;
 pub mod mem;
-pub mod sync;
-pub mod syscall;
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs
index de108665e9f..5b240351c20 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs
@@ -5,8 +5,8 @@ use std::rc::{Rc, Weak};
 use std::time::Duration;
 
 use crate::concurrency::VClock;
-use crate::shims::unix::fd::{FdId, FileDescriptionRef, WeakFileDescriptionRef};
-use crate::shims::unix::*;
+use crate::shims::files::{FdId, FileDescription, FileDescriptionRef, WeakFileDescriptionRef};
+use crate::shims::unix::UnixFileDescription;
 use crate::*;
 
 /// An `Epoll` file descriptor connects file handles and epoll events
@@ -152,8 +152,14 @@ impl FileDescription for Epoll {
     ) -> InterpResult<'tcx, io::Result<()>> {
         interp_ok(Ok(()))
     }
+
+    fn as_unix(&self) -> &dyn UnixFileDescription {
+        self
+    }
 }
 
+impl UnixFileDescription for Epoll {}
+
 /// The table of all EpollEventInterest.
 /// The BTreeMap key is the FdId of an active file description registered with
 /// any epoll instance. The value is a list of EpollEventInterest associated
@@ -539,7 +545,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     )?;
                     if is_updated {
                         // Edge-triggered notification only notify one thread even if there are
-                        // multiple threads block on the same epfd.
+                        // multiple threads blocked on the same epfd.
 
                         // This unwrap can never fail because if the current epoll instance were
                         // closed, the upgrade of weak_epoll_interest
@@ -595,7 +601,7 @@ fn check_and_update_one_event_interest<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
 ) -> InterpResult<'tcx, bool> {
     // Get the bitmask of ready events for a file description.
-    let ready_events_bitmask = fd_ref.get_epoll_ready_events()?.get_event_bitmask(ecx);
+    let ready_events_bitmask = fd_ref.as_unix().get_epoll_ready_events()?.get_event_bitmask(ecx);
     let epoll_event_interest = interest.borrow();
     // This checks if any of the events specified in epoll_event_interest.events
     // match those in ready_events.
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs
index 63b7d37b13e..4bbe417ea8d 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs
@@ -4,9 +4,9 @@ use std::io;
 use std::io::ErrorKind;
 
 use crate::concurrency::VClock;
-use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef};
-use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _};
-use crate::shims::unix::*;
+use crate::shims::files::{FileDescription, FileDescriptionRef, WeakFileDescriptionRef};
+use crate::shims::unix::UnixFileDescription;
+use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _};
 use crate::*;
 
 /// Maximum value that the eventfd counter can hold.
@@ -37,17 +37,6 @@ impl FileDescription for Event {
         "event"
     }
 
-    fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
-        // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags
-        // need to be supported in the future, the check should be added here.
-
-        interp_ok(EpollReadyEvents {
-            epollin: self.counter.get() != 0,
-            epollout: self.counter.get() != MAX_COUNTER,
-            ..EpollReadyEvents::new()
-        })
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
@@ -121,6 +110,23 @@ impl FileDescription for Event {
         let weak_eventfd = self_ref.downgrade();
         eventfd_write(num, buf_place, dest, weak_eventfd, ecx)
     }
+
+    fn as_unix(&self) -> &dyn UnixFileDescription {
+        self
+    }
+}
+
+impl UnixFileDescription for Event {
+    fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
+        // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags
+        // need to be supported in the future, the check should be added here.
+
+        interp_ok(EpollReadyEvents {
+            epollin: self.counter.get() != 0,
+            epollout: self.counter.get() != MAX_COUNTER,
+            ..EpollReadyEvents::new()
+        })
+    }
 }
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -144,9 +150,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        // eventfd is Linux specific.
-        this.assert_target_os("linux", "eventfd");
-
         let val = this.read_scalar(val)?.to_u32()?;
         let mut flags = this.read_scalar(flags)?.to_i32()?;
 
@@ -211,10 +214,10 @@ fn eventfd_write<'tcx>(
                 eventfd.clock.borrow_mut().join(clock);
             });
 
-            // When this function is called, the addition is guaranteed to not exceed u64::MAX - 1.
+            // Store new counter value.
             eventfd.counter.set(new_count);
 
-            // When any of the event happened, we check and update the status of all supported event
+            // The state changed; we check and update the status of all supported event
             // types for current file description.
             ecx.check_and_update_readiness(&eventfd_ref)?;
 
@@ -228,10 +231,11 @@ fn eventfd_write<'tcx>(
                 ecx.unblock_thread(thread_id, BlockReason::Eventfd)?;
             }
 
-            // Return how many bytes we wrote.
+            // Return how many bytes we consumed from the user-provided buffer.
             return ecx.write_int(buf_place.layout.size.bytes(), dest);
         }
         None | Some(u64::MAX) => {
+            // We can't update the state, so we have to block.
             if eventfd.is_nonblock {
                 return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest);
             }
@@ -251,6 +255,7 @@ fn eventfd_write<'tcx>(
                         weak_eventfd: WeakFileDescriptionRef,
                     }
                     @unblock = |this| {
+                        // When we get unblocked, try again.
                         eventfd_write(num, buf_place, &dest, weak_eventfd, this)
                     }
                 ),
@@ -276,9 +281,10 @@ fn eventfd_read<'tcx>(
     // an eventfd file description.
     let eventfd = eventfd_ref.downcast::<Event>().unwrap();
 
-    // Block when counter == 0.
+    // Set counter to 0, get old value.
     let counter = eventfd.counter.replace(0);
 
+    // Block when counter == 0.
     if counter == 0 {
         if eventfd.is_nonblock {
             return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest);
@@ -297,6 +303,7 @@ fn eventfd_read<'tcx>(
                     weak_eventfd: WeakFileDescriptionRef,
                 }
                 @unblock = |this| {
+                    // When we get unblocked, try again.
                     eventfd_read(buf_place, &dest, weak_eventfd, this)
                 }
             ),
@@ -305,10 +312,10 @@ fn eventfd_read<'tcx>(
         // Synchronize with all prior `write` calls to this FD.
         ecx.acquire_clock(&eventfd.clock.borrow());
 
-        // Give old counter value to userspace, and set counter value to 0.
+        // Return old counter value into user-space buffer.
         ecx.write_int(counter, &buf_place)?;
 
-        // When any of the events happened, we check and update the status of all supported event
+        // The state changed; we check and update the status of all supported event
         // types for current file description.
         ecx.check_and_update_readiness(&eventfd_ref)?;
 
@@ -322,7 +329,7 @@ fn eventfd_read<'tcx>(
             ecx.unblock_thread(thread_id, BlockReason::Eventfd)?;
         }
 
-        // Tell userspace how many bytes we read.
+        // Tell userspace how many bytes we put into the buffer.
         return ecx.write_int(buf_place.layout.size.bytes(), dest);
     }
     interp_ok(())
diff --git a/src/tools/miri/src/shims/unix/linux_like/mod.rs b/src/tools/miri/src/shims/unix/linux_like/mod.rs
new file mode 100644
index 00000000000..1a22539a4ee
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux_like/mod.rs
@@ -0,0 +1,4 @@
+pub mod epoll;
+pub mod eventfd;
+pub mod sync;
+pub mod syscall;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs
index 51124fb2a00..51124fb2a00 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs
diff --git a/src/tools/miri/src/shims/unix/linux/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs
index 9f6935f096b..e9a32a26326 100644
--- a/src/tools/miri/src/shims/unix/linux/syscall.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs
@@ -1,9 +1,9 @@
 use rustc_abi::ExternAbi;
 use rustc_span::Symbol;
 
-use self::shims::unix::linux::eventfd::EvalContextExt as _;
 use crate::helpers::check_min_arg_count;
-use crate::shims::unix::linux::sync::futex;
+use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
+use crate::shims::unix::linux_like::sync::futex;
 use crate::*;
 
 pub fn syscall<'tcx>(
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 003025916cd..103bea08620 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -40,19 +40,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             "stat" | "stat64" | "stat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_stat(path, buf)?;
+                let result = this.macos_fbsd_solaris_stat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "lstat" | "lstat64" | "lstat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_lstat(path, buf)?;
+                let result = this.macos_fbsd_solaris_lstat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "fstat" | "fstat64" | "fstat$INODE64" => {
                 let [fd, buf] =
                     this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fbsd_fstat(fd, buf)?;
+                let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "opendir$INODE64" => {
diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs
index c8c25c636ee..660e4ded5cd 100644
--- a/src/tools/miri/src/shims/unix/mod.rs
+++ b/src/tools/miri/src/shims/unix/mod.rs
@@ -10,15 +10,16 @@ mod unnamed_socket;
 
 mod android;
 mod freebsd;
-mod linux;
+pub mod linux;
+mod linux_like;
 mod macos;
 mod solarish;
 
 // All the Unix-specific extension traits
 pub use self::env::{EvalContextExt as _, UnixEnvVars};
-pub use self::fd::{EvalContextExt as _, FdTable, FileDescription};
+pub use self::fd::{EvalContextExt as _, UnixFileDescription};
 pub use self::fs::{DirTable, EvalContextExt as _};
-pub use self::linux::epoll::EpollInterestTable;
+pub use self::linux_like::epoll::EpollInterestTable;
 pub use self::mem::EvalContextExt as _;
 pub use self::sync::EvalContextExt as _;
 pub use self::thread::{EvalContextExt as _, ThreadNameResult};
diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
index 526b64cff69..e4529170368 100644
--- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
@@ -1,6 +1,7 @@
 use rustc_abi::ExternAbi;
 use rustc_span::Symbol;
 
+use crate::shims::unix::foreign_items::EvalContextExt as _;
 use crate::shims::unix::*;
 use crate::*;
 
@@ -56,6 +57,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
 
+            // File related shims
+            "stat" | "stat64" => {
+                let [path, buf] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_solaris_stat(path, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+            "lstat" | "lstat64" => {
+                let [path, buf] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_solaris_lstat(path, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+            "fstat" | "fstat64" => {
+                let [fd, buf] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+
             // Miscellaneous
             "___errno" => {
                 let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
@@ -112,6 +133,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_null(dest)?;
             }
 
+            "__sysconf_xpg7" => {
+                let [val] =
+                    this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
+                let result = this.sysconf(val)?;
+                this.write_scalar(result, dest)?;
+            }
+
             _ => return interp_ok(EmulateItemResult::NotSupported),
         }
         interp_ok(EmulateItemResult::NeedsReturn)
diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs
index 8ccce7c1986..40a76ea7439 100644
--- a/src/tools/miri/src/shims/unix/unnamed_socket.rs
+++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs
@@ -10,9 +10,11 @@ use std::io::{ErrorKind, Read};
 use rustc_abi::Size;
 
 use crate::concurrency::VClock;
-use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef};
-use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _};
-use crate::shims::unix::*;
+use crate::shims::files::{
+    EvalContextExt as _, FileDescription, FileDescriptionRef, WeakFileDescriptionRef,
+};
+use crate::shims::unix::UnixFileDescription;
+use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _};
 use crate::*;
 
 /// The maximum capacity of the socketpair buffer in bytes.
@@ -60,52 +62,6 @@ impl FileDescription for AnonSocket {
         "socketpair"
     }
 
-    fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
-        // We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags.
-        // If other event flags need to be supported in the future, the check should be added here.
-
-        let mut epoll_ready_events = EpollReadyEvents::new();
-
-        // Check if it is readable.
-        if let Some(readbuf) = &self.readbuf {
-            if !readbuf.borrow().buf.is_empty() {
-                epoll_ready_events.epollin = true;
-            }
-        } else {
-            // Without a read buffer, reading never blocks, so we are always ready.
-            epoll_ready_events.epollin = true;
-        }
-
-        // Check if is writable.
-        if let Some(peer_fd) = self.peer_fd().upgrade() {
-            if let Some(writebuf) = &peer_fd.downcast::<AnonSocket>().unwrap().readbuf {
-                let data_size = writebuf.borrow().buf.len();
-                let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size);
-                if available_space != 0 {
-                    epoll_ready_events.epollout = true;
-                }
-            } else {
-                // Without a write buffer, writing never blocks.
-                epoll_ready_events.epollout = true;
-            }
-        } else {
-            // Peer FD has been closed. This always sets both the RDHUP and HUP flags
-            // as we do not support `shutdown` that could be used to partially close the stream.
-            epoll_ready_events.epollrdhup = true;
-            epoll_ready_events.epollhup = true;
-            // Since the peer is closed, even if no data is available reads will return EOF and
-            // writes will return EPIPE. In other words, they won't block, so we mark this as ready
-            // for read and write.
-            epoll_ready_events.epollin = true;
-            epoll_ready_events.epollout = true;
-            // If there is data lost in peer_fd, set EPOLLERR.
-            if self.peer_lost_data.get() {
-                epoll_ready_events.epollerr = true;
-            }
-        }
-        interp_ok(epoll_ready_events)
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
@@ -134,11 +90,9 @@ impl FileDescription for AnonSocket {
         dest: &MPlaceTy<'tcx>,
         ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx> {
-        let mut bytes = vec![0; len];
-
         // Always succeed on read size 0.
         if len == 0 {
-            return ecx.return_read_success(ptr, &bytes, 0, dest);
+            return ecx.return_read_success(ptr, &[], 0, dest);
         }
 
         let Some(readbuf) = &self.readbuf else {
@@ -146,12 +100,11 @@ impl FileDescription for AnonSocket {
             // corresponding ErrorKind variant.
             throw_unsup_format!("reading from the write end of a pipe");
         };
-        let mut readbuf = readbuf.borrow_mut();
-        if readbuf.buf.is_empty() {
+        if readbuf.borrow().buf.is_empty() {
             if self.peer_fd().upgrade().is_none() {
                 // Socketpair with no peer and empty buffer.
                 // 0 bytes successfully read indicates end-of-file.
-                return ecx.return_read_success(ptr, &bytes, 0, dest);
+                return ecx.return_read_success(ptr, &[], 0, dest);
             } else {
                 if self.is_nonblock {
                     // Non-blocking socketpair with writer and empty buffer.
@@ -167,31 +120,8 @@ impl FileDescription for AnonSocket {
                 }
             }
         }
-
-        // Synchronize with all previous writes to this buffer.
-        // FIXME: this over-synchronizes; a more precise approach would be to
-        // only sync with the writes whose data we will read.
-        ecx.acquire_clock(&readbuf.clock);
-
-        // Do full read / partial read based on the space available.
-        // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior.
-        let actual_read_size = readbuf.buf.read(&mut bytes).unwrap();
-
-        // Need to drop before others can access the readbuf again.
-        drop(readbuf);
-
-        // A notification should be provided for the peer file description even when it can
-        // only write 1 byte. This implementation is not compliant with the actual Linux kernel
-        // implementation. For optimization reasons, the kernel will only mark the file description
-        // as "writable" when it can write more than a certain number of bytes. Since we
-        // don't know what that *certain number* is, we will provide a notification every time
-        // a read is successful. This might result in our epoll emulation providing more
-        // notifications than the real system.
-        if let Some(peer_fd) = self.peer_fd().upgrade() {
-            ecx.check_and_update_readiness(&peer_fd)?;
-        }
-
-        ecx.return_read_success(ptr, &bytes, actual_read_size, dest)
+        // TODO: We might need to decide what to do if peer_fd is closed when read is blocked.
+        anonsocket_read(self, self.peer_fd().upgrade(), len, ptr, dest, ecx)
     }
 
     fn write<'tcx>(
@@ -221,9 +151,8 @@ impl FileDescription for AnonSocket {
             // corresponding ErrorKind variant.
             throw_unsup_format!("writing to the reading end of a pipe");
         };
-        let mut writebuf = writebuf.borrow_mut();
-        let data_size = writebuf.buf.len();
-        let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size);
+        let available_space =
+            MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(writebuf.borrow().buf.len());
         if available_space == 0 {
             if self.is_nonblock {
                 // Non-blocking socketpair with a full buffer.
@@ -233,23 +162,138 @@ impl FileDescription for AnonSocket {
                 throw_unsup_format!("socketpair/pipe/pipe2 write: blocking isn't supported yet");
             }
         }
-        // Remember this clock so `read` can synchronize with us.
-        ecx.release_clock(|clock| {
-            writebuf.clock.join(clock);
-        });
-        // Do full write / partial write based on the space available.
-        let actual_write_size = len.min(available_space);
-        let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
-        writebuf.buf.extend(&bytes[..actual_write_size]);
+        anonsocket_write(available_space, &peer_fd, ptr, len, dest, ecx)
+    }
 
-        // Need to stop accessing peer_fd so that it can be notified.
-        drop(writebuf);
+    fn as_unix(&self) -> &dyn UnixFileDescription {
+        self
+    }
+}
 
-        // Notification should be provided for peer fd as it became readable.
-        // The kernel does this even if the fd was already readable before, so we follow suit.
+/// Write to AnonSocket based on the space available and return the written byte size.
+fn anonsocket_write<'tcx>(
+    available_space: usize,
+    peer_fd: &FileDescriptionRef,
+    ptr: Pointer,
+    len: usize,
+    dest: &MPlaceTy<'tcx>,
+    ecx: &mut MiriInterpCx<'tcx>,
+) -> InterpResult<'tcx> {
+    let Some(writebuf) = &peer_fd.downcast::<AnonSocket>().unwrap().readbuf else {
+        // FIXME: This should return EBADF, but there's no nice way to do that as there's no
+        // corresponding ErrorKind variant.
+        throw_unsup_format!("writing to the reading end of a pipe")
+    };
+    let mut writebuf = writebuf.borrow_mut();
+
+    // Remember this clock so `read` can synchronize with us.
+    ecx.release_clock(|clock| {
+        writebuf.clock.join(clock);
+    });
+    // Do full write / partial write based on the space available.
+    let actual_write_size = len.min(available_space);
+    let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
+    writebuf.buf.extend(&bytes[..actual_write_size]);
+
+    // Need to stop accessing peer_fd so that it can be notified.
+    drop(writebuf);
+
+    // Notification should be provided for peer fd as it became readable.
+    // The kernel does this even if the fd was already readable before, so we follow suit.
+    ecx.check_and_update_readiness(peer_fd)?;
+
+    ecx.return_write_success(actual_write_size, dest)
+}
+
+/// Read from AnonSocket and return the number of bytes read.
+fn anonsocket_read<'tcx>(
+    anonsocket: &AnonSocket,
+    peer_fd: Option<FileDescriptionRef>,
+    len: usize,
+    ptr: Pointer,
+    dest: &MPlaceTy<'tcx>,
+    ecx: &mut MiriInterpCx<'tcx>,
+) -> InterpResult<'tcx> {
+    let mut bytes = vec![0; len];
+
+    let Some(readbuf) = &anonsocket.readbuf else {
+        // FIXME: This should return EBADF, but there's no nice way to do that as there's no
+        // corresponding ErrorKind variant.
+        throw_unsup_format!("reading from the write end of a pipe")
+    };
+    let mut readbuf = readbuf.borrow_mut();
+
+    // Synchronize with all previous writes to this buffer.
+    // FIXME: this over-synchronizes; a more precise approach would be to
+    // only sync with the writes whose data we will read.
+    ecx.acquire_clock(&readbuf.clock);
+
+    // Do full read / partial read based on the space available.
+    // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior.
+    let actual_read_size = readbuf.buf.read(&mut bytes[..]).unwrap();
+
+    // Need to drop before others can access the readbuf again.
+    drop(readbuf);
+
+    // A notification should be provided for the peer file description even when it can
+    // only write 1 byte. This implementation is not compliant with the actual Linux kernel
+    // implementation. For optimization reasons, the kernel will only mark the file description
+    // as "writable" when it can write more than a certain number of bytes. Since we
+    // don't know what that *certain number* is, we will provide a notification every time
+    // a read is successful. This might result in our epoll emulation providing more
+    // notifications than the real system.
+    if let Some(peer_fd) = peer_fd {
         ecx.check_and_update_readiness(&peer_fd)?;
+    }
+
+    ecx.return_read_success(ptr, &bytes, actual_read_size, dest)
+}
+
+impl UnixFileDescription for AnonSocket {
+    fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
+        // We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags.
+        // If other event flags need to be supported in the future, the check should be added here.
+
+        let mut epoll_ready_events = EpollReadyEvents::new();
 
-        ecx.return_write_success(actual_write_size, dest)
+        // Check if it is readable.
+        if let Some(readbuf) = &self.readbuf {
+            if !readbuf.borrow().buf.is_empty() {
+                epoll_ready_events.epollin = true;
+            }
+        } else {
+            // Without a read buffer, reading never blocks, so we are always ready.
+            epoll_ready_events.epollin = true;
+        }
+
+        // Check if is writable.
+        if let Some(peer_fd) = self.peer_fd().upgrade() {
+            if let Some(writebuf) = &peer_fd.downcast::<AnonSocket>().unwrap().readbuf {
+                let data_size = writebuf.borrow().buf.len();
+                let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size);
+                if available_space != 0 {
+                    epoll_ready_events.epollout = true;
+                }
+            } else {
+                // Without a write buffer, writing never blocks.
+                epoll_ready_events.epollout = true;
+            }
+        } else {
+            // Peer FD has been closed. This always sets both the RDHUP and HUP flags
+            // as we do not support `shutdown` that could be used to partially close the stream.
+            epoll_ready_events.epollrdhup = true;
+            epoll_ready_events.epollhup = true;
+            // Since the peer is closed, even if no data is available reads will return EOF and
+            // writes will return EPIPE. In other words, they won't block, so we mark this as ready
+            // for read and write.
+            epoll_ready_events.epollin = true;
+            epoll_ready_events.epollout = true;
+            // If there is data lost in peer_fd, set EPOLLERR.
+            if self.peer_lost_data.get() {
+                epoll_ready_events.epollerr = true;
+            }
+        }
+        interp_ok(epoll_ready_events)
     }
 }
 
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index a1fad6f9af4..d6a180451d7 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -383,7 +383,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_int(1, dest)?;
             }
             "TlsFree" => {
-                let [key] = this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?;
+                let [key] =
+                    this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?;
                 let key = u128::from(this.read_scalar(key)?.to_u32()?);
                 this.machine.tls.delete_tls_key(key)?;
 
diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs
index 65d29b2c6ba..81a96103db4 100644
--- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs
+++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs
@@ -14,7 +14,7 @@ use std::thread;
 // 2. Thread 2 blocks.
 // 3. Thread 3 unblocks both thread 1 and thread 2.
 // 4. Thread 1 reads.
-// 5. Thread 2's `read` deadlocked.
+// 5. Thread 2's `read` can never complete -> deadlocked.
 
 fn main() {
     // eventfd write will block when EFD_NONBLOCK flag is clear
@@ -23,7 +23,6 @@ fn main() {
     let fd = unsafe { libc::eventfd(0, flags) };
 
     let thread1 = thread::spawn(move || {
-        thread::park();
         let mut buf: [u8; 8] = [0; 8];
         // This read will block initially.
         let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() };
@@ -33,7 +32,6 @@ fn main() {
     });
 
     let thread2 = thread::spawn(move || {
-        thread::park();
         let mut buf: [u8; 8] = [0; 8];
         // This read will block initially, then get unblocked by thread3, then get blocked again
         // because the `read` in thread1 executes first and set the counter to 0 again.
@@ -45,7 +43,6 @@ fn main() {
     });
 
     let thread3 = thread::spawn(move || {
-        thread::park();
         let sized_8_data = 1_u64.to_ne_bytes();
         // Write 1 to the counter, so both thread1 and thread2 will unblock.
         let res: i64 = unsafe {
@@ -55,10 +52,6 @@ fn main() {
         assert_eq!(res, 8);
     });
 
-    thread1.thread().unpark();
-    thread2.thread().unpark();
-    thread3.thread().unpark();
-
     thread1.join().unwrap();
     thread2.join().unwrap();
     thread3.join().unwrap();
diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs
index f9d34d2fb58..7a2a6f4eb1a 100644
--- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs
+++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs
@@ -14,7 +14,7 @@ use std::thread;
 // 2. Thread 2 blocks.
 // 3. Thread 3 unblocks both thread 1 and thread 2.
 // 4. Thread 1 writes u64::MAX.
-// 5. Thread 2's `write` deadlocked.
+// 5. Thread 2's `write` can never complete -> deadlocked.
 fn main() {
     // eventfd write will block when EFD_NONBLOCK flag is clear
     // and the addition caused counter to exceed u64::MAX - 1.
@@ -28,7 +28,6 @@ fn main() {
     assert_eq!(res, 8);
 
     let thread1 = thread::spawn(move || {
-        thread::park();
         let sized_8_data = (u64::MAX - 1).to_ne_bytes();
         let res: i64 = unsafe {
             libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
@@ -38,7 +37,6 @@ fn main() {
     });
 
     let thread2 = thread::spawn(move || {
-        thread::park();
         let sized_8_data = (u64::MAX - 1).to_ne_bytes();
         // Write u64::MAX - 1, so the all subsequent write will block.
         let res: i64 = unsafe {
@@ -52,7 +50,6 @@ fn main() {
     });
 
     let thread3 = thread::spawn(move || {
-        thread::park();
         let mut buf: [u8; 8] = [0; 8];
         // This will unblock both `write` in thread1 and thread2.
         let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() };
@@ -61,10 +58,6 @@ fn main() {
         assert_eq!(counter, (u64::MAX - 1));
     });
 
-    thread1.thread().unpark();
-    thread2.thread().unpark();
-    thread3.thread().unpark();
-
     thread1.join().unwrap();
     thread2.join().unwrap();
     thread3.join().unwrap();
diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
index 398bc92b392..7bef687e339 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
+++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
@@ -2,7 +2,7 @@
 //! and we only read one of them, we do not synchronize with the other events
 //! and therefore still report a data race for things that need to see the second event
 //! to be considered synchronized.
-//@only-target: linux
+//@only-target: linux android
 // ensure deterministic schedule
 //@compile-flags: -Zmiri-preemption-rate=0
 
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
index 7f5ec477e19..1c6c2f70c1d 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
+++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
@@ -5,7 +5,6 @@
 //@error-in-other-file: deadlock
 
 use std::convert::TryInto;
-use std::thread;
 use std::thread::spawn;
 
 // Using `as` cast since `EPOLLET` wraps around
@@ -41,10 +40,10 @@ fn check_epoll_wait<const N: usize>(
 
 // Test if only one thread is unblocked if multiple threads blocked on same epfd.
 // Expected execution:
-// 1. Thread 2 blocks.
-// 2. Thread 3 blocks.
-// 3. Thread 1 unblocks thread 3.
-// 4. Thread 2 deadlocks.
+// 1. Thread 1 blocks.
+// 2. Thread 2 blocks.
+// 3. Thread 3 unblocks thread 2.
+// 4. Thread 1 deadlocks.
 fn main() {
     // Create an epoll instance.
     let epfd = unsafe { libc::epoll_create1(0) };
@@ -65,30 +64,21 @@ fn main() {
     let expected_value = fds[0] as u64;
     check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], 0);
 
-    let thread1 = spawn(move || {
-        thread::park();
-        let data = "abcde".as_bytes().as_ptr();
-        let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
-        assert_eq!(res, 5);
-    });
-
     let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
     let expected_value = fds[0] as u64;
-    let thread2 = spawn(move || {
-        thread::park();
+    let thread1 = spawn(move || {
         check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
         //~^ERROR: deadlocked
     });
-    let thread3 = spawn(move || {
-        thread::park();
+    let thread2 = spawn(move || {
         check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
     });
 
-    thread2.thread().unpark();
-    thread::yield_now();
-    thread3.thread().unpark();
-    thread::yield_now();
-    thread1.thread().unpark();
+    let thread3 = spawn(move || {
+        let data = "abcde".as_bytes().as_ptr();
+        let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
+        assert_eq!(res, 5);
+    });
 
     thread1.join().unwrap();
     thread2.join().unwrap();
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
index 010dabc1364..b29794f68dd 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
@@ -1,4 +1,10 @@
 error: deadlock: the evaluated program deadlocked
+   |
+   = note: the evaluated program deadlocked
+   = note: (no span available)
+   = note: BACKTRACE on thread `unnamed-ID`:
+
+error: deadlock: the evaluated program deadlocked
   --> RUSTLIB/std/src/sys/pal/PLATFORM/thread.rs:LL:CC
    |
 LL |         let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
@@ -11,16 +17,10 @@ LL |         let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
 note: inside `main`
   --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC
    |
-LL |     thread2.join().unwrap();
+LL |     thread1.join().unwrap();
    |     ^^^^^^^^^^^^^^
 
 error: deadlock: the evaluated program deadlocked
-   |
-   = note: the evaluated program deadlocked
-   = note: (no span available)
-   = note: BACKTRACE on thread `unnamed-ID`:
-
-error: deadlock: the evaluated program deadlocked
   --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC
    |
 LL |         check_epoll_wait::<TAG>(epfd, &[(expected_event, expected_value)], -1);
diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs
index 2dd87ea6083..42943d58191 100644
--- a/src/tools/miri/tests/fail/breakpoint.rs
+++ b/src/tools/miri/tests/fail/breakpoint.rs
@@ -1,7 +1,5 @@
 #![feature(core_intrinsics)]
 
 fn main() {
-    unsafe {
-        core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
-    };
+    core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr
index ca98e81f1f4..f203cb0c15f 100644
--- a/src/tools/miri/tests/fail/breakpoint.stderr
+++ b/src/tools/miri/tests/fail/breakpoint.stderr
@@ -1,8 +1,8 @@
 error: abnormal termination: trace/breakpoint trap
   --> tests/fail/breakpoint.rs:LL:CC
    |
-LL |         core::intrinsics::breakpoint()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
+LL |     core::intrinsics::breakpoint();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
    |
    = note: BACKTRACE:
    = note: inside `main` at tests/fail/breakpoint.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs
new file mode 100644
index 00000000000..bd02e7f5fb4
--- /dev/null
+++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs
@@ -0,0 +1,27 @@
+// Validity makes this fail at the wrong place.
+//@compile-flags: -Zmiri-disable-validation
+use std::mem;
+
+// This enum has untagged variant idx 1, with niche_variants being 0..=2
+// and niche_start being 2.
+// That means the untagged variants is in the niche variant range!
+// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant.
+#[derive(Copy, Clone, PartialEq)]
+enum Foo {
+    Var1,
+    Var2(bool),
+    Var3,
+}
+
+fn main() {
+    unsafe {
+        assert!(Foo::Var2(false) == mem::transmute(0u8));
+        assert!(Foo::Var2(true) == mem::transmute(1u8));
+        assert!(Foo::Var1 == mem::transmute(2u8));
+        assert!(Foo::Var3 == mem::transmute(4u8));
+
+        let invalid: Foo = mem::transmute(3u8);
+        assert!(matches!(invalid, Foo::Var2(_)));
+        //~^ ERROR: invalid tag
+    }
+}
diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr
new file mode 100644
index 00000000000..759dbc36380
--- /dev/null
+++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: enum value has invalid tag: 0x03
+  --> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
+   |
+LL |         assert!(matches!(invalid, Foo::Var2(_)));
+   |                          ^^^^^^^ enum value has invalid tag: 0x03
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.rs b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.rs
deleted file mode 100644
index cebad507ea9..00000000000
--- a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//@compile-flags: -Zmiri-ignore-leaks
-
-// https://plv.mpi-sws.org/scfix/paper.pdf
-// 2.2 Second Problem: SC Fences are Too Weak
-// This test should pass under the C++20 model Rust is using.
-// Unfortunately, Miri's weak memory emulation only follows the C++11 model
-// as we don't know how to correctly emulate C++20's revised SC semantics,
-// so we have to stick to C++11 emulation from existing research.
-
-use std::sync::atomic::Ordering::*;
-use std::sync::atomic::{AtomicUsize, fence};
-use std::thread::spawn;
-
-// Spins until it reads the given value
-fn reads_value(loc: &AtomicUsize, val: usize) -> usize {
-    while loc.load(Relaxed) != val {
-        std::hint::spin_loop();
-    }
-    val
-}
-
-// We can't create static items because we need to run each test
-// multiple tests
-fn static_atomic(val: usize) -> &'static AtomicUsize {
-    let ret = Box::leak(Box::new(AtomicUsize::new(val)));
-    // A workaround to put the initialization value in the store buffer.
-    // See https://github.com/rust-lang/miri/issues/2164
-    ret.load(Relaxed);
-    ret
-}
-
-fn test_cpp20_rwc_syncs() {
-    /*
-    int main() {
-        atomic_int x = 0;
-        atomic_int y = 0;
-
-        {{{ x.store(1,mo_relaxed);
-        ||| { r1=x.load(mo_relaxed).readsvalue(1);
-              fence(mo_seq_cst);
-              r2=y.load(mo_relaxed); }
-        ||| { y.store(1,mo_relaxed);
-              fence(mo_seq_cst);
-              r3=x.load(mo_relaxed); }
-        }}}
-        return 0;
-    }
-    */
-    let x = static_atomic(0);
-    let y = static_atomic(0);
-
-    let j1 = spawn(move || {
-        x.store(1, Relaxed);
-    });
-
-    let j2 = spawn(move || {
-        reads_value(&x, 1);
-        fence(SeqCst);
-        y.load(Relaxed)
-    });
-
-    let j3 = spawn(move || {
-        y.store(1, Relaxed);
-        fence(SeqCst);
-        x.load(Relaxed)
-    });
-
-    j1.join().unwrap();
-    let b = j2.join().unwrap();
-    let c = j3.join().unwrap();
-
-    // We cannot write assert_ne!() since ui_test's fail
-    // tests expect exit status 1, whereas panics produce 101.
-    // Our ui_test does not yet support overriding failure status codes.
-    if (b, c) == (0, 0) {
-        // This *should* be unreachable, but Miri will reach it.
-        unsafe {
-            std::hint::unreachable_unchecked(); //~ERROR: unreachable
-        }
-    }
-}
-
-pub fn main() {
-    for _ in 0..500 {
-        test_cpp20_rwc_syncs();
-    }
-}
diff --git a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
deleted file mode 100644
index 5185845568e..00000000000
--- a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: Undefined Behavior: entering unreachable code
-  --> tests/fail/should-pass/cpp20_rwc_syncs.rs:LL:CC
-   |
-LL |             std::hint::unreachable_unchecked();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
-   |
-   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
-   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
-   = note: inside `test_cpp20_rwc_syncs` at tests/fail/should-pass/cpp20_rwc_syncs.rs:LL:CC
-note: inside `main`
-  --> tests/fail/should-pass/cpp20_rwc_syncs.rs:LL:CC
-   |
-LL |         test_cpp20_rwc_syncs();
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
index 46eb5778b32..3ccfecc6fb3 100644
--- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
+++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
@@ -3,17 +3,14 @@
 //@only-on-host
 
 fn main() {
-    test_pointer();
-
-    test_simple();
-
-    test_nested();
-
-    test_static();
+    test_access_pointer();
+    test_access_simple();
+    test_access_nested();
+    test_access_static();
 }
 
-// Test void function that dereferences a pointer and prints its contents from C.
-fn test_pointer() {
+/// Test function that dereferences an int pointer and prints its contents from C.
+fn test_access_pointer() {
     extern "C" {
         fn print_pointer(ptr: *const i32);
     }
@@ -23,8 +20,8 @@ fn test_pointer() {
     unsafe { print_pointer(&x) };
 }
 
-// Test function that dereferences a simple struct pointer and accesses a field.
-fn test_simple() {
+/// Test function that dereferences a simple struct pointer and accesses a field.
+fn test_access_simple() {
     #[repr(C)]
     struct Simple {
         field: i32,
@@ -39,8 +36,8 @@ fn test_simple() {
     assert_eq!(unsafe { access_simple(&simple) }, -42);
 }
 
-// Test function that dereferences nested struct pointers and accesses fields.
-fn test_nested() {
+/// Test function that dereferences nested struct pointers and accesses fields.
+fn test_access_nested() {
     use std::ptr::NonNull;
 
     #[derive(Debug, PartialEq, Eq)]
@@ -61,8 +58,8 @@ fn test_nested() {
     assert_eq!(unsafe { access_nested(&nested_2) }, 97);
 }
 
-// Test function that dereferences static struct pointers and accesses fields.
-fn test_static() {
+/// Test function that dereferences a static struct pointer and accesses fields.
+fn test_access_static() {
     #[repr(C)]
     struct Static {
         value: i32,
diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs
new file mode 100644
index 00000000000..a92e63a4da6
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs
@@ -0,0 +1,202 @@
+// Only works on Unix targets
+//@ignore-target: windows wasm
+//@only-on-host
+//@compile-flags: -Zmiri-permissive-provenance
+
+#![feature(box_as_ptr)]
+
+use std::mem::MaybeUninit;
+use std::ptr::null;
+
+fn main() {
+    test_increment_int();
+    test_init_int();
+    test_init_array();
+    test_init_static_inner();
+    test_exposed();
+    test_swap_ptr();
+    test_swap_ptr_tuple();
+    test_overwrite_dangling();
+    test_pass_dangling();
+    test_swap_ptr_triple_dangling();
+    test_return_ptr();
+}
+
+/// Test function that modifies an int.
+fn test_increment_int() {
+    extern "C" {
+        fn increment_int(ptr: *mut i32);
+    }
+
+    let mut x = 11;
+
+    unsafe { increment_int(&mut x) };
+    assert_eq!(x, 12);
+}
+
+/// Test function that initializes an int.
+fn test_init_int() {
+    extern "C" {
+        fn init_int(ptr: *mut i32, val: i32);
+    }
+
+    let mut x = MaybeUninit::<i32>::uninit();
+    let val = 21;
+
+    let x = unsafe {
+        init_int(x.as_mut_ptr(), val);
+        x.assume_init()
+    };
+    assert_eq!(x, val);
+}
+
+/// Test function that initializes an array.
+fn test_init_array() {
+    extern "C" {
+        fn init_array(ptr: *mut i32, len: usize, val: i32);
+    }
+
+    const LEN: usize = 3;
+    let mut array = MaybeUninit::<[i32; LEN]>::uninit();
+    let val = 31;
+
+    let array = unsafe {
+        init_array(array.as_mut_ptr().cast::<i32>(), LEN, val);
+        array.assume_init()
+    };
+    assert_eq!(array, [val; LEN]);
+}
+
+/// Test function that initializes an int pointed to by an immutable static.
+fn test_init_static_inner() {
+    #[repr(C)]
+    struct SyncPtr {
+        ptr: *mut i32,
+    }
+    unsafe impl Sync for SyncPtr {}
+
+    extern "C" {
+        fn init_static_inner(s_ptr: *const SyncPtr, val: i32);
+    }
+
+    static mut INNER: MaybeUninit<i32> = MaybeUninit::uninit();
+    #[allow(static_mut_refs)]
+    static STATIC: SyncPtr = SyncPtr { ptr: unsafe { INNER.as_mut_ptr() } };
+    let val = 41;
+
+    let inner = unsafe {
+        init_static_inner(&STATIC, val);
+        INNER.assume_init()
+    };
+    assert_eq!(inner, val);
+}
+
+// Test function that marks an allocation as exposed.
+fn test_exposed() {
+    extern "C" {
+        fn ignore_ptr(ptr: *const i32);
+    }
+
+    let x = 51;
+    let ptr = &raw const x;
+    let p = ptr.addr();
+
+    unsafe { ignore_ptr(ptr) };
+    assert_eq!(unsafe { *(p as *const i32) }, x);
+}
+
+/// Test function that swaps two pointers and exposes the alloc of an int.
+fn test_swap_ptr() {
+    extern "C" {
+        fn swap_ptr(pptr0: *mut *const i32, pptr1: *mut *const i32);
+    }
+
+    let x = 61;
+    let (mut ptr0, mut ptr1) = (&raw const x, null());
+
+    unsafe { swap_ptr(&mut ptr0, &mut ptr1) };
+    assert_eq!(unsafe { *ptr1 }, x);
+}
+
+/// Test function that swaps two pointers in a struct and exposes the alloc of an int.
+fn test_swap_ptr_tuple() {
+    #[repr(C)]
+    struct Tuple {
+        ptr0: *const i32,
+        ptr1: *const i32,
+    }
+
+    extern "C" {
+        fn swap_ptr_tuple(t_ptr: *mut Tuple);
+    }
+
+    let x = 71;
+    let mut tuple = Tuple { ptr0: &raw const x, ptr1: null() };
+
+    unsafe { swap_ptr_tuple(&mut tuple) }
+    assert_eq!(unsafe { *tuple.ptr1 }, x);
+}
+
+/// Test function that interacts with a dangling pointer.
+fn test_overwrite_dangling() {
+    extern "C" {
+        fn overwrite_ptr(pptr: *mut *const i32);
+    }
+
+    let b = Box::new(81);
+    let mut ptr = Box::as_ptr(&b);
+    drop(b);
+
+    unsafe { overwrite_ptr(&mut ptr) };
+    assert_eq!(ptr, null());
+}
+
+/// Test function that passes a dangling pointer.
+fn test_pass_dangling() {
+    extern "C" {
+        fn ignore_ptr(ptr: *const i32);
+    }
+
+    let b = Box::new(91);
+    let ptr = Box::as_ptr(&b);
+    drop(b);
+
+    unsafe { ignore_ptr(ptr) };
+}
+
+/// Test function that interacts with a struct storing a dangling pointer.
+fn test_swap_ptr_triple_dangling() {
+    #[repr(C)]
+    struct Triple {
+        ptr0: *const i32,
+        ptr1: *const i32,
+        ptr2: *const i32,
+    }
+
+    extern "C" {
+        fn swap_ptr_triple_dangling(t_ptr: *const Triple);
+    }
+
+    let x = 101;
+    let b = Box::new(111);
+    let ptr = Box::as_ptr(&b);
+    drop(b);
+    let z = 121;
+    let triple = Triple { ptr0: &raw const x, ptr1: ptr, ptr2: &raw const z };
+
+    unsafe { swap_ptr_triple_dangling(&triple) }
+    assert_eq!(unsafe { *triple.ptr2 }, x);
+}
+
+/// Test function that directly returns its pointer argument.
+fn test_return_ptr() {
+    extern "C" {
+        fn return_ptr(ptr: *const i32) -> *const i32;
+    }
+
+    let x = 131;
+    let ptr = &raw const x;
+
+    let ptr = unsafe { return_ptr(ptr) };
+    assert_eq!(unsafe { *ptr }, x);
+}
diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c
index 540845d53a7..3b427d6033e 100644
--- a/src/tools/miri/tests/native-lib/ptr_read_access.c
+++ b/src/tools/miri/tests/native-lib/ptr_read_access.c
@@ -3,13 +3,13 @@
 // See comments in build_native_lib()
 #define EXPORT __attribute__((visibility("default")))
 
-/* Test: test_pointer */
+/* Test: test_access_pointer */
 
 EXPORT void print_pointer(const int *ptr) {
   printf("printing pointer dereference from C: %d\n", *ptr);
 }
 
-/* Test: test_simple */
+/* Test: test_access_simple */
 
 typedef struct Simple {
   int field;
@@ -19,7 +19,7 @@ EXPORT int access_simple(const Simple *s_ptr) {
   return s_ptr->field;
 }
 
-/* Test: test_nested */
+/* Test: test_access_nested */
 
 typedef struct Nested {
   int value;
@@ -38,7 +38,7 @@ EXPORT int access_nested(const Nested *n_ptr) {
   return n_ptr->value;
 }
 
-/* Test: test_static */
+/* Test: test_access_static */
 
 typedef struct Static {
     int value;
diff --git a/src/tools/miri/tests/native-lib/ptr_write_access.c b/src/tools/miri/tests/native-lib/ptr_write_access.c
new file mode 100644
index 00000000000..b54c5d86b21
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/ptr_write_access.c
@@ -0,0 +1,90 @@
+#include <stddef.h>
+
+// See comments in build_native_lib()
+#define EXPORT __attribute__((visibility("default")))
+
+/* Test: test_increment_int */
+
+EXPORT void increment_int(int *ptr) {
+  *ptr += 1;
+}
+
+/* Test: test_init_int */
+
+EXPORT void init_int(int *ptr, int val) {
+  *ptr = val;
+}
+
+/* Test: test_init_array */
+
+EXPORT void init_array(int *array, size_t len, int val) {
+  for (size_t i = 0; i < len; i++) {
+    array[i] = val;
+  }
+}
+
+/* Test: test_init_static_inner */
+
+typedef struct SyncPtr {
+    int *ptr;
+} SyncPtr;
+
+EXPORT void init_static_inner(const SyncPtr *s_ptr, int val) {
+  *(s_ptr->ptr) = val;
+}
+
+/* Tests: test_exposed, test_pass_dangling */
+
+EXPORT void ignore_ptr(__attribute__((unused)) const int *ptr) {
+  return;
+}
+
+/* Test: test_expose_int */
+EXPORT void expose_int(const int *int_ptr, const int **pptr) {
+  *pptr = int_ptr;
+}
+
+/* Test: test_swap_ptr */
+
+EXPORT void swap_ptr(const int **pptr0, const int **pptr1) {
+  const int *tmp = *pptr0;
+  *pptr0 = *pptr1;
+  *pptr1 = tmp;
+}
+
+/* Test: test_swap_ptr_tuple */
+
+typedef struct Tuple {
+    int *ptr0;
+    int *ptr1;
+} Tuple;
+
+EXPORT void swap_ptr_tuple(Tuple *t_ptr) {
+  int *tmp = t_ptr->ptr0;
+  t_ptr->ptr0 = t_ptr->ptr1;
+  t_ptr->ptr1 = tmp;
+}
+
+/* Test: test_overwrite_dangling */
+
+EXPORT void overwrite_ptr(const int **pptr) {
+  *pptr = NULL;
+}
+
+/* Test: test_swap_ptr_triple_dangling */
+
+typedef struct Triple {
+    int *ptr0;
+    int *ptr1;
+    int *ptr2;
+} Triple;
+
+EXPORT void swap_ptr_triple_dangling(Triple *t_ptr) {
+  int *tmp = t_ptr->ptr0;
+  t_ptr->ptr0 = t_ptr->ptr2;
+  t_ptr->ptr2 = tmp;
+}
+
+EXPORT const int *return_ptr(const int *ptr) {
+  return ptr;
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
index 9bcc776e281..e3c42b2701c 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
@@ -1,4 +1,4 @@
-//@only-target: linux
+//@only-target: linux android
 // test_epoll_block_then_unblock and test_epoll_race depend on a deterministic schedule.
 //@compile-flags: -Zmiri-preemption-rate=0
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
index 288c1d41f30..111e639c864 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
@@ -1,4 +1,4 @@
-//@only-target: linux
+//@only-target: linux android
 
 use std::convert::TryInto;
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
index dd9c0eb0b54..2e453215ec9 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
@@ -1,4 +1,4 @@
-//@only-target: linux
+//@only-target: linux android
 // test_race, test_blocking_read and test_blocking_write depend on a deterministic schedule.
 //@compile-flags: -Zmiri-preemption-rate=0
 
@@ -197,7 +197,6 @@ fn test_two_threads_blocked_on_eventfd() {
     assert_eq!(res, 8);
 
     let thread1 = thread::spawn(move || {
-        thread::park();
         let sized_8_data = 1_u64.to_ne_bytes();
         let res: i64 = unsafe {
             libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
@@ -207,7 +206,6 @@ fn test_two_threads_blocked_on_eventfd() {
     });
 
     let thread2 = thread::spawn(move || {
-        thread::park();
         let sized_8_data = 1_u64.to_ne_bytes();
         let res: i64 = unsafe {
             libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
@@ -217,7 +215,6 @@ fn test_two_threads_blocked_on_eventfd() {
     });
 
     let thread3 = thread::spawn(move || {
-        thread::park();
         let mut buf: [u8; 8] = [0; 8];
         // This will unblock previously blocked eventfd read.
         let res = read_bytes(fd, &mut buf);
@@ -227,10 +224,6 @@ fn test_two_threads_blocked_on_eventfd() {
         assert_eq!(counter, (u64::MAX - 1));
     });
 
-    thread1.thread().unpark();
-    thread2.thread().unpark();
-    thread3.thread().unpark();
-
     thread1.join().unwrap();
     thread2.join().unwrap();
     thread3.join().unwrap();
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
index a35c92636ce..fd7fc801dc2 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
@@ -47,9 +47,12 @@ fn test_readlink() {
     assert_eq!(res, small_buf.len() as isize);
 
     // Test that we report a proper error for a missing path.
-    let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap();
     let res = unsafe {
-        libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len())
+        libc::readlink(
+            c"MIRI_MISSING_FILE_NAME".as_ptr(),
+            small_buf.as_mut_ptr().cast(),
+            small_buf.len(),
+        )
     };
     assert_eq!(res, -1);
     assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
index ab3fd6733ff..cffcf4a867f 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
@@ -2,7 +2,6 @@
 //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
 //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT"
 
-use std::ffi::CString;
 use std::fs;
 use std::io::{Error, ErrorKind};
 
@@ -13,10 +12,9 @@ fn main() {
     }
 
     // test `readlink`
-    let symlink_c_str = CString::new("foo.txt").unwrap();
     let mut buf = vec![0; "foo_link.txt".len() + 1];
     unsafe {
-        assert_eq!(libc::readlink(symlink_c_str.as_ptr(), buf.as_mut_ptr(), buf.len()), -1);
+        assert_eq!(libc::readlink(c"foo.txt".as_ptr(), buf.as_mut_ptr(), buf.len()), -1);
         assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES));
     }
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
index 10be78798a6..727533a9de6 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
@@ -55,12 +55,12 @@ fn test_memcpy() {
 }
 
 fn test_strcpy() {
-    use std::ffi::{CStr, CString};
+    use std::ffi::CStr;
 
     // case: src_size equals dest_size
     unsafe {
-        let src = CString::new("rust").unwrap();
-        let size = src.as_bytes_with_nul().len();
+        let src = c"rust";
+        let size = src.to_bytes_with_nul().len();
         let dest = libc::malloc(size);
         libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
         assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
@@ -69,8 +69,8 @@ fn test_strcpy() {
 
     // case: src_size is less than dest_size
     unsafe {
-        let src = CString::new("rust").unwrap();
-        let size = src.as_bytes_with_nul().len();
+        let src = c"rust";
+        let size = src.to_bytes_with_nul().len();
         let dest = libc::malloc(size + 1);
         libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
         assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs b/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs
new file mode 100644
index 00000000000..09885ce839d
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs
@@ -0,0 +1,16 @@
+//@ignore-target: windows # Supported only on unixes
+
+fn main() {
+    unsafe {
+        let mut buf = vec![0u8; 32];
+        assert_eq!(libc::strerror_r(libc::EPERM, buf.as_mut_ptr().cast(), buf.len()), 0);
+        let mut buf2 = vec![0u8; 64];
+        assert_eq!(libc::strerror_r(-1i32, buf2.as_mut_ptr().cast(), buf2.len()), 0);
+        // This buffer is deliberately too small so this triggers ERANGE.
+        let mut buf3 = vec![0u8; 2];
+        assert_eq!(
+            libc::strerror_r(libc::E2BIG, buf3.as_mut_ptr().cast(), buf3.len()),
+            libc::ERANGE
+        );
+    }
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs
new file mode 100644
index 00000000000..b832b3033b7
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs
@@ -0,0 +1,19 @@
+//@ignore-target: windows # Supported only on unixes
+
+fn test_sysconfbasic() {
+    unsafe {
+        let ncpus = libc::sysconf(libc::_SC_NPROCESSORS_CONF);
+        assert!(ncpus >= 1);
+        let psz = libc::sysconf(libc::_SC_PAGESIZE);
+        assert!(psz % 4096 == 0);
+        // note that in reality it can return -1 (no hard limit) on some platforms.
+        let gwmax = libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX);
+        assert!(gwmax >= 512);
+        let omax = libc::sysconf(libc::_SC_OPEN_MAX);
+        assert_eq!(omax, 65536);
+    }
+}
+
+fn main() {
+    test_sysconfbasic();
+}
diff --git a/src/tools/miri/tests/pass/0weak_memory_consistency.rs b/src/tools/miri/tests/pass/0weak_memory_consistency.rs
index 10f7aed9418..ce5b8be07f0 100644
--- a/src/tools/miri/tests/pass/0weak_memory_consistency.rs
+++ b/src/tools/miri/tests/pass/0weak_memory_consistency.rs
@@ -1,4 +1,4 @@
-//@compile-flags: -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows -Zmiri-provenance-gc=10000
+//@compile-flags: -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows -Zmiri-disable-validation -Zmiri-provenance-gc=10000
 // This test's runtime explodes if the GC interval is set to 1 (which we do in CI), so we
 // override it internally back to the default frequency.
 
@@ -22,7 +22,7 @@
 // Available: https://ss265.host.cs.st-andrews.ac.uk/papers/n3132.pdf.
 
 use std::sync::atomic::Ordering::*;
-use std::sync::atomic::{AtomicBool, AtomicI32, fence};
+use std::sync::atomic::{AtomicBool, AtomicI32, Ordering, fence};
 use std::thread::spawn;
 
 #[derive(Copy, Clone)]
@@ -34,19 +34,15 @@ unsafe impl<T> Sync for EvilSend<T> {}
 // We can't create static items because we need to run each test
 // multiple times
 fn static_atomic(val: i32) -> &'static AtomicI32 {
-    let ret = Box::leak(Box::new(AtomicI32::new(val)));
-    ret.store(val, Relaxed); // work around https://github.com/rust-lang/miri/issues/2164
-    ret
+    Box::leak(Box::new(AtomicI32::new(val)))
 }
 fn static_atomic_bool(val: bool) -> &'static AtomicBool {
-    let ret = Box::leak(Box::new(AtomicBool::new(val)));
-    ret.store(val, Relaxed); // work around https://github.com/rust-lang/miri/issues/2164
-    ret
+    Box::leak(Box::new(AtomicBool::new(val)))
 }
 
 // Spins until it acquires a pre-determined value.
-fn acquires_value(loc: &AtomicI32, val: i32) -> i32 {
-    while loc.load(Acquire) != val {
+fn loads_value(loc: &AtomicI32, ord: Ordering, val: i32) -> i32 {
+    while loc.load(ord) != val {
         std::hint::spin_loop();
     }
     val
@@ -69,7 +65,7 @@ fn test_corr() {
     }); //                                           |                    |
     #[rustfmt::skip] //                              |synchronizes-with   |happens-before
     let j3 = spawn(move || { //                      |                    |
-        acquires_value(&y, 1); // <------------------+                    |
+        loads_value(&y, Acquire, 1); // <------------+                    |
         x.load(Relaxed) // <----------------------------------------------+
         // The two reads on x are ordered by hb, so they cannot observe values
         // differently from the modification order. If the first read observed
@@ -94,12 +90,12 @@ fn test_wrc() {
     }); //                                           |                     |
     #[rustfmt::skip] //                              |synchronizes-with    |
     let j2 = spawn(move || { //                      |                     |
-        acquires_value(&x, 1); // <------------------+                     |
+        loads_value(&x, Acquire, 1); // <------------+                     |
         y.store(1, Release); // ---------------------+                     |happens-before
     }); //                                           |                     |
     #[rustfmt::skip] //                              |synchronizes-with    |
     let j3 = spawn(move || { //                      |                     |
-        acquires_value(&y, 1); // <------------------+                     |
+        loads_value(&y, Acquire, 1); // <------------+                     |
         x.load(Relaxed) // <-----------------------------------------------+
     });
 
@@ -125,7 +121,7 @@ fn test_message_passing() {
     #[rustfmt::skip] //                              |synchronizes-with  | happens-before
     let j2 = spawn(move || { //                      |                   |
         let x = x; // avoid field capturing          |                   |
-        acquires_value(&y, 1); // <------------------+                   |
+        loads_value(&y, Acquire, 1); // <------------+                   |
         unsafe { *x.0 } // <---------------------------------------------+
     });
 
@@ -268,9 +264,6 @@ fn test_iriw_sc_rlx() {
     let x = static_atomic_bool(false);
     let y = static_atomic_bool(false);
 
-    x.store(false, Relaxed);
-    y.store(false, Relaxed);
-
     let a = spawn(move || x.store(true, Relaxed));
     let b = spawn(move || y.store(true, Relaxed));
     let c = spawn(move || {
@@ -290,6 +283,152 @@ fn test_iriw_sc_rlx() {
     assert!(c || d);
 }
 
+// Similar to `test_iriw_sc_rlx` but with fences instead of SC accesses.
+fn test_cpp20_sc_fence_fix() {
+    let x = static_atomic_bool(false);
+    let y = static_atomic_bool(false);
+
+    let thread1 = spawn(|| {
+        let a = x.load(Relaxed);
+        fence(SeqCst);
+        let b = y.load(Relaxed);
+        (a, b)
+    });
+
+    let thread2 = spawn(|| {
+        x.store(true, Relaxed);
+    });
+    let thread3 = spawn(|| {
+        y.store(true, Relaxed);
+    });
+
+    let thread4 = spawn(|| {
+        let c = y.load(Relaxed);
+        fence(SeqCst);
+        let d = x.load(Relaxed);
+        (c, d)
+    });
+
+    let (a, b) = thread1.join().unwrap();
+    thread2.join().unwrap();
+    thread3.join().unwrap();
+    let (c, d) = thread4.join().unwrap();
+    let bad = a == true && b == false && c == true && d == false;
+    assert!(!bad);
+}
+
+// https://plv.mpi-sws.org/scfix/paper.pdf
+// 2.2 Second Problem: SC Fences are Too Weak
+fn test_cpp20_rwc_syncs() {
+    /*
+    int main() {
+        atomic_int x = 0;
+        atomic_int y = 0;
+        {{{ x.store(1,mo_relaxed);
+        ||| { r1=x.load(mo_relaxed).readsvalue(1);
+              fence(mo_seq_cst);
+              r2=y.load(mo_relaxed); }
+        ||| { y.store(1,mo_relaxed);
+              fence(mo_seq_cst);
+              r3=x.load(mo_relaxed); }
+        }}}
+        return 0;
+    }
+    */
+    let x = static_atomic(0);
+    let y = static_atomic(0);
+
+    let j1 = spawn(move || {
+        x.store(1, Relaxed);
+    });
+
+    let j2 = spawn(move || {
+        loads_value(&x, Relaxed, 1);
+        fence(SeqCst);
+        y.load(Relaxed)
+    });
+
+    let j3 = spawn(move || {
+        y.store(1, Relaxed);
+        fence(SeqCst);
+        x.load(Relaxed)
+    });
+
+    j1.join().unwrap();
+    let b = j2.join().unwrap();
+    let c = j3.join().unwrap();
+
+    assert!((b, c) != (0, 0));
+}
+
+/// This checks that the *last* thing the SC fence does is act like a release fence.
+/// See <https://github.com/rust-lang/miri/pull/4057#issuecomment-2522296601>.
+fn test_sc_fence_release() {
+    let x = static_atomic(0);
+    let y = static_atomic(0);
+    let z = static_atomic(0);
+    let k = static_atomic(0);
+
+    let j1 = spawn(move || {
+        x.store(1, Relaxed);
+        fence(SeqCst);
+        k.store(1, Relaxed);
+    });
+    let j2 = spawn(move || {
+        y.store(1, Relaxed);
+        fence(SeqCst);
+        z.store(1, Relaxed);
+    });
+
+    let j3 = spawn(move || {
+        let kval = k.load(Acquire);
+        let yval = y.load(Relaxed);
+        (kval, yval)
+    });
+    let j4 = spawn(move || {
+        let zval = z.load(Acquire);
+        let xval = x.load(Relaxed);
+        (zval, xval)
+    });
+
+    j1.join().unwrap();
+    j2.join().unwrap();
+    let (kval, yval) = j3.join().unwrap();
+    let (zval, xval) = j4.join().unwrap();
+
+    let bad = kval == 1 && yval == 0 && zval == 1 && xval == 0;
+    assert!(!bad);
+}
+
+/// Test that SC fences and accesses sync correctly with each other.
+fn test_sc_fence_access() {
+    /*
+        Wx1 sc
+        Ry0 sc
+        ||
+        Wy1 rlx
+        SC-fence
+        Rx0 rlx
+    */
+    let x = static_atomic(0);
+    let y = static_atomic(0);
+
+    let j1 = spawn(move || {
+        x.store(1, SeqCst);
+        y.load(SeqCst)
+    });
+    let j2 = spawn(move || {
+        y.store(1, Relaxed);
+        fence(SeqCst);
+        x.load(Relaxed)
+    });
+
+    let v1 = j1.join().unwrap();
+    let v2 = j2.join().unwrap();
+    let bad = v1 == 0 && v2 == 0;
+    assert!(!bad);
+}
+
 pub fn main() {
     for _ in 0..50 {
         test_single_thread();
@@ -301,5 +440,9 @@ pub fn main() {
         test_sc_store_buffering();
         test_sync_through_rmw_and_fences();
         test_iriw_sc_rlx();
+        test_cpp20_sc_fence_fix();
+        test_cpp20_rwc_syncs();
+        test_sc_fence_release();
+        test_sc_fence_access();
     }
 }
diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs
index cac26bfe146..979a6d1cbe0 100644
--- a/src/tools/miri/tests/pass/async-closure-captures.rs
+++ b/src/tools/miri/tests/pass/async-closure-captures.rs
@@ -1,6 +1,6 @@
 // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs
index 9b2fc2948bf..ad9822fa46d 100644
--- a/src/tools/miri/tests/pass/async-closure-drop.rs
+++ b/src/tools/miri/tests/pass/async-closure-drop.rs
@@ -1,4 +1,4 @@
-#![feature(async_closure, noop_waker, async_fn_traits)]
+#![feature(async_closure, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs
index 721af578883..979b83687e4 100644
--- a/src/tools/miri/tests/pass/async-closure.rs
+++ b/src/tools/miri/tests/pass/async-closure.rs
@@ -1,4 +1,4 @@
-#![feature(async_closure, noop_waker, async_fn_traits)]
+#![feature(async_closure, async_fn_traits)]
 #![allow(unused)]
 
 use std::future::Future;
diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs
index 53e3476f620..a455f377e85 100644
--- a/src/tools/miri/tests/pass/async-drop.rs
+++ b/src/tools/miri/tests/pass/async-drop.rs
@@ -6,7 +6,7 @@
 // please consider modifying rustc's async drop test at
 // `tests/ui/async-await/async-drop.rs`.
 
-#![feature(async_drop, impl_trait_in_assoc_type, noop_waker, async_closure)]
+#![feature(async_drop, impl_trait_in_assoc_type, async_closure)]
 #![allow(incomplete_features, dead_code)]
 
 // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests
diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs
index 67ec2e26b30..42c60bb4fab 100644
--- a/src/tools/miri/tests/pass/async-fn.rs
+++ b/src/tools/miri/tests/pass/async-fn.rs
@@ -1,5 +1,4 @@
 #![feature(never_type)]
-#![feature(noop_waker)]
 
 use std::future::Future;
 
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs
deleted file mode 100644
index 3fff7921aff..00000000000
--- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-//@normalize-stderr-test: "::<.*>" -> ""
-
-#[inline(never)]
-fn func_a() -> Box<[*mut ()]> {
-    func_b::<u8>()
-}
-#[inline(never)]
-fn func_b<T>() -> Box<[*mut ()]> {
-    func_c()
-}
-
-macro_rules! invoke_func_d {
-    () => {
-        func_d()
-    };
-}
-
-#[inline(never)]
-fn func_c() -> Box<[*mut ()]> {
-    invoke_func_d!()
-}
-#[inline(never)]
-fn func_d() -> Box<[*mut ()]> {
-    unsafe { miri_get_backtrace(0) }
-}
-
-fn main() {
-    let mut seen_main = false;
-    let frames = func_a();
-    for frame in frames.iter() {
-        let miri_frame = unsafe { miri_resolve_frame(*frame, 0) };
-        let name = String::from_utf8(miri_frame.name.into()).unwrap();
-        let filename = String::from_utf8(miri_frame.filename.into()).unwrap();
-
-        if name == "func_a" {
-            assert_eq!(func_a as *mut (), miri_frame.fn_ptr);
-        }
-
-        // Print every frame to stderr.
-        let out = format!("{}:{}:{} ({})", filename, miri_frame.lineno, miri_frame.colno, name);
-        eprintln!("{}", out);
-        // Print the 'main' frame (and everything before it) to stdout, skipping
-        // the printing of internal (and possibly fragile) libstd frames.
-        // Stdout is less normalized so we see more, but it also means we can print less
-        // as platform differences would lead to test suite failures.
-        if !seen_main {
-            println!("{}", out);
-            seen_main = name == "main";
-        }
-    }
-}
-
-// This goes at the bottom of the file so that we can change it
-// without disturbing line numbers of the functions in the backtrace.
-
-extern "Rust" {
-    fn miri_get_backtrace(flags: u64) -> Box<[*mut ()]>;
-    fn miri_resolve_frame(ptr: *mut (), flags: u64) -> MiriFrame;
-}
-
-#[derive(Debug)]
-#[repr(C)]
-struct MiriFrame {
-    name: Box<[u8]>,
-    filename: Box<[u8]>,
-    lineno: u32,
-    colno: u32,
-    fn_ptr: *mut (),
-}
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr
deleted file mode 100644
index 9849a1aa74e..00000000000
--- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-tests/pass/backtrace/backtrace-api-v0.rs:LL:CC (func_d)
-tests/pass/backtrace/backtrace-api-v0.rs:LL:CC (func_c)
-tests/pass/backtrace/backtrace-api-v0.rs:LL:CC (func_b)
-tests/pass/backtrace/backtrace-api-v0.rs:LL:CC (func_a)
-tests/pass/backtrace/backtrace-api-v0.rs:LL:CC (main)
-RUSTLIB/core/src/ops/function.rs:LL:CC (<fn() as std::ops::FnOnce<()>>::call_once - shim(fn()))
-RUSTLIB/std/src/sys/backtrace.rs:LL:CC (std::sys::backtrace::__rust_begin_short_backtrace)
-RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start::{closure#0})
-RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
-RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
-RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#1})
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
-RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
-RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal)
-RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start)
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout
deleted file mode 100644
index 8c1bc5c353e..00000000000
--- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout
+++ /dev/null
@@ -1,5 +0,0 @@
-tests/pass/backtrace/backtrace-api-v0.rs:24:14 (func_d)
-tests/pass/backtrace/backtrace-api-v0.rs:14:9 (func_c)
-tests/pass/backtrace/backtrace-api-v0.rs:9:5 (func_b::<u8>)
-tests/pass/backtrace/backtrace-api-v0.rs:5:5 (func_a)
-tests/pass/backtrace/backtrace-api-v0.rs:29:18 (main)
diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs
index dab589b4651..1ce0dd3c9d5 100644
--- a/src/tools/miri/tests/pass/dyn-star.rs
+++ b/src/tools/miri/tests/pass/dyn-star.rs
@@ -1,7 +1,6 @@
 #![feature(dyn_star)]
 #![allow(incomplete_features)]
 #![feature(custom_inner_attributes)]
-#![feature(noop_waker)]
 // rustfmt destroys `dyn* Trait` syntax
 #![rustfmt::skip]
 
diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs
index a5c4bc5e0d9..7145be334a1 100644
--- a/src/tools/miri/tests/pass/function_pointers.rs
+++ b/src/tools/miri/tests/pass/function_pointers.rs
@@ -1,3 +1,5 @@
+#![allow(unpredictable_function_pointer_comparisons)]
+
 use std::mem;
 
 trait Answer {
diff --git a/src/tools/miri/tests/pass/future-self-referential.rs b/src/tools/miri/tests/pass/future-self-referential.rs
index 8aeb26a7a95..88d52d8f1c1 100644
--- a/src/tools/miri/tests/pass/future-self-referential.rs
+++ b/src/tools/miri/tests/pass/future-self-referential.rs
@@ -1,6 +1,5 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(noop_waker)]
 
 use std::future::*;
 use std::marker::PhantomPinned;
diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs
index b46cf1ddf65..b688405c4b1 100644
--- a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs
+++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs
@@ -1,44 +1,75 @@
-#![feature(core_intrinsics)]
+#![feature(core_intrinsics, portable_simd)]
+use std::intrinsics::simd::simd_relaxed_fma;
 use std::intrinsics::{fmuladdf32, fmuladdf64};
+use std::simd::prelude::*;
 
-fn main() {
-    let mut saw_zero = false;
-    let mut saw_nonzero = false;
+fn ensure_both_happen(f: impl Fn() -> bool) -> bool {
+    let mut saw_true = false;
+    let mut saw_false = false;
     for _ in 0..50 {
-        let a = std::hint::black_box(0.1_f64);
-        let b = std::hint::black_box(0.2);
-        let c = std::hint::black_box(-a * b);
-        // It is unspecified whether the following operation is fused or not. The
-        // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused.
-        let x = unsafe { fmuladdf64(a, b, c) };
-        if x == 0.0 {
-            saw_zero = true;
+        let b = f();
+        if b {
+            saw_true = true;
         } else {
-            saw_nonzero = true;
+            saw_false = true;
+        }
+        if saw_true && saw_false {
+            return true;
         }
     }
+    false
+}
+
+fn main() {
     assert!(
-        saw_zero && saw_nonzero,
+        ensure_both_happen(|| {
+            let a = std::hint::black_box(0.1_f64);
+            let b = std::hint::black_box(0.2);
+            let c = std::hint::black_box(-a * b);
+            // It is unspecified whether the following operation is fused or not. The
+            // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused.
+            let x = unsafe { fmuladdf64(a, b, c) };
+            x == 0.0
+        }),
         "`fmuladdf64` failed to be evaluated as both fused and unfused"
     );
 
-    let mut saw_zero = false;
-    let mut saw_nonzero = false;
-    for _ in 0..50 {
-        let a = std::hint::black_box(0.1_f32);
-        let b = std::hint::black_box(0.2);
-        let c = std::hint::black_box(-a * b);
-        // It is unspecified whether the following operation is fused or not. The
-        // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused.
-        let x = unsafe { fmuladdf32(a, b, c) };
-        if x == 0.0 {
-            saw_zero = true;
-        } else {
-            saw_nonzero = true;
-        }
-    }
     assert!(
-        saw_zero && saw_nonzero,
+        ensure_both_happen(|| {
+            let a = std::hint::black_box(0.1_f32);
+            let b = std::hint::black_box(0.2);
+            let c = std::hint::black_box(-a * b);
+            // It is unspecified whether the following operation is fused or not. The
+            // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused.
+            let x = unsafe { fmuladdf32(a, b, c) };
+            x == 0.0
+        }),
         "`fmuladdf32` failed to be evaluated as both fused and unfused"
     );
+
+    assert!(
+        ensure_both_happen(|| {
+            let a = f32x4::splat(std::hint::black_box(0.1));
+            let b = f32x4::splat(std::hint::black_box(0.2));
+            let c = std::hint::black_box(-a * b);
+            let x = unsafe { simd_relaxed_fma(a, b, c) };
+            // Whether we fuse or not is a per-element decision, so sometimes these should be
+            // the same and sometimes not.
+            x[0] == x[1]
+        }),
+        "`simd_relaxed_fma` failed to be evaluated as both fused and unfused"
+    );
+
+    assert!(
+        ensure_both_happen(|| {
+            let a = f64x4::splat(std::hint::black_box(0.1));
+            let b = f64x4::splat(std::hint::black_box(0.2));
+            let c = std::hint::black_box(-a * b);
+            let x = unsafe { simd_relaxed_fma(a, b, c) };
+            // Whether we fuse or not is a per-element decision, so sometimes these should be
+            // the same and sometimes not.
+            x[0] == x[1]
+        }),
+        "`simd_relaxed_fma` failed to be evaluated as both fused and unfused"
+    );
 }
diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
index f560669dd63..acd3502f528 100644
--- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
@@ -40,6 +40,17 @@ fn simd_ops_f32() {
         f32x4::splat(-3.2).mul_add(b, f32x4::splat(f32::NEG_INFINITY)),
         f32x4::splat(f32::NEG_INFINITY)
     );
+
+    unsafe {
+        assert_eq!(intrinsics::simd_relaxed_fma(a, b, a), (a * b) + a);
+        assert_eq!(intrinsics::simd_relaxed_fma(b, b, a), (b * b) + a);
+        assert_eq!(intrinsics::simd_relaxed_fma(a, b, b), (a * b) + b);
+        assert_eq!(
+            intrinsics::simd_relaxed_fma(f32x4::splat(-3.2), b, f32x4::splat(f32::NEG_INFINITY)),
+            f32x4::splat(f32::NEG_INFINITY)
+        );
+    }
+
     assert_eq!((a * a).sqrt(), a);
     assert_eq!((b * b).sqrt(), b.abs());
 
@@ -94,6 +105,17 @@ fn simd_ops_f64() {
         f64x4::splat(-3.2).mul_add(b, f64x4::splat(f64::NEG_INFINITY)),
         f64x4::splat(f64::NEG_INFINITY)
     );
+
+    unsafe {
+        assert_eq!(intrinsics::simd_relaxed_fma(a, b, a), (a * b) + a);
+        assert_eq!(intrinsics::simd_relaxed_fma(b, b, a), (b * b) + a);
+        assert_eq!(intrinsics::simd_relaxed_fma(a, b, b), (a * b) + b);
+        assert_eq!(
+            intrinsics::simd_relaxed_fma(f64x4::splat(-3.2), b, f64x4::splat(f64::NEG_INFINITY)),
+            f64x4::splat(f64::NEG_INFINITY)
+        );
+    }
+
     assert_eq!((a * a).sqrt(), a);
     assert_eq!((b * b).sqrt(), b.abs());
 
diff --git a/src/tools/miri/tests/pass/issues/issue-91636.rs b/src/tools/miri/tests/pass/issues/issue-91636.rs
index 00370165812..d0cadcd2c70 100644
--- a/src/tools/miri/tests/pass/issues/issue-91636.rs
+++ b/src/tools/miri/tests/pass/issues/issue-91636.rs
@@ -1,3 +1,5 @@
+#![allow(unpredictable_function_pointer_comparisons)]
+
 type BuiltIn = for<'a> fn(&str);
 
 struct Function {
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
index ccee2221e29..1931b6c9d79 100644
--- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
+++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
@@ -1,5 +1,3 @@
-#![feature(noop_waker)]
-
 use std::future::Future;
 use std::pin::Pin;
 use std::task::{Context, Poll, Waker};
diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs
index 1a93a6bf664..5aafddd99b9 100644
--- a/src/tools/miri/tests/pass/move-data-across-await-point.rs
+++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs
@@ -1,4 +1,3 @@
-#![feature(noop_waker)]
 use std::future::Future;
 use std::ptr;
 
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 81151f4ac47..3e514d95ee9 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -27,8 +27,11 @@ fn main() {
     test_file_sync();
     test_errors();
     test_rename();
-    test_directory();
-    test_canonicalize();
+    // solarish needs to support readdir/readdir64 for these tests.
+    if cfg!(not(any(target_os = "solaris", target_os = "illumos"))) {
+        test_directory();
+        test_canonicalize();
+    }
     test_from_raw_os_error();
     #[cfg(unix)]
     test_pread_pwrite();
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 9553a37c9a8..9b9542b88a9 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -64,6 +64,7 @@ fn build_native_lib() -> PathBuf {
             // FIXME: Automate gathering of all relevant C source files in the directory.
             "tests/native-lib/scalar_arguments.c",
             "tests/native-lib/ptr_read_access.c",
+            "tests/native-lib/ptr_write_access.c",
             // Ensure we notice serious problems in the C code.
             "-Wall",
             "-Wextra",
diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake
index 218d88d8721..849ed1f4fc5 100644
--- a/src/tools/nix-dev-shell/envrc-flake
+++ b/src/tools/nix-dev-shell/envrc-flake
@@ -1,7 +1,7 @@
 # If you want to use this as an .envrc file to create a shell with necessery components 
 # to develop rustc, use the following command in the root of the rusr checkout:
 #	
-# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && echo .envrc >> .git/info/exclude
+# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell
 
 if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then
   use flake path:./src/tools/nix-dev-shell
diff --git a/src/tools/nix-dev-shell/envrc-shell b/src/tools/nix-dev-shell/envrc-shell
index fb7231a6c30..d8f900fe86a 100644
--- a/src/tools/nix-dev-shell/envrc-shell
+++ b/src/tools/nix-dev-shell/envrc-shell
@@ -1,7 +1,7 @@
 # If you want to use this as an .envrc file to create a shell with necessery components 
 # to develop rustc, use the following command in the root of the rusr checkout:
 #	
-# ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc && echo .envrc >> .git/info/exclude
+# ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc
 
 use nix ./src/tools/nix-dev-shell/shell.nix
   
diff --git a/src/tools/nix-dev-shell/flake.nix b/src/tools/nix-dev-shell/flake.nix
index 8ab5e097427..1b838bd2f7b 100644
--- a/src/tools/nix-dev-shell/flake.nix
+++ b/src/tools/nix-dev-shell/flake.nix
@@ -24,9 +24,8 @@
           # Avoid creating text files for ICEs.
           RUSTC_ICE = "0";
           # Provide `libstdc++.so.6` for the self-contained lld.
-          LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [
-            stdenv.cc.cc.lib
-          ]}";
+          # Provide `libz.so.1`.
+          LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
         };
       }
     );
diff --git a/src/tools/nix-dev-shell/shell.nix b/src/tools/nix-dev-shell/shell.nix
index 8a5cbb7c89e..a3f5969bd81 100644
--- a/src/tools/nix-dev-shell/shell.nix
+++ b/src/tools/nix-dev-shell/shell.nix
@@ -13,7 +13,6 @@ pkgs.mkShell {
   # Avoid creating text files for ICEs.
   RUSTC_ICE = "0";
   # Provide `libstdc++.so.6` for the self-contained lld.
-  LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [
-    stdenv.cc.cc.lib
-  ]}";
+  # Provide `libz.so.1`
+  LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
 }
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 328b48e04d2..a639dc20a60 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -14,6 +14,7 @@ import json
 import datetime
 import collections
 import textwrap
+
 try:
     import urllib2
     from urllib2 import HTTPError
@@ -21,7 +22,7 @@ except ImportError:
     import urllib.request as urllib2
     from urllib.error import HTTPError
 try:
-    import typing # noqa: F401 FIXME: py2
+    import typing  # noqa: F401 FIXME: py2
 except ImportError:
     pass
 
@@ -29,40 +30,41 @@ except ImportError:
 # These should be collaborators of the rust-lang/rust repository (with at least
 # read privileges on it). CI will fail otherwise.
 MAINTAINERS = {
-    'book': {'carols10cents'},
-    'nomicon': {'frewsxcv', 'Gankra', 'JohnTitor'},
-    'reference': {'Havvy', 'matthewjasper', 'ehuss'},
-    'rust-by-example': {'marioidival'},
-    'embedded-book': {'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof'},
-    'edition-guide': {'ehuss'},
-    'rustc-dev-guide': {'spastorino', 'amanjeev', 'JohnTitor'},
+    "book": {"carols10cents"},
+    "nomicon": {"frewsxcv", "Gankra", "JohnTitor"},
+    "reference": {"Havvy", "matthewjasper", "ehuss"},
+    "rust-by-example": {"marioidival"},
+    "embedded-book": {"adamgreig", "andre-richter", "jamesmunns", "therealprof"},
+    "edition-guide": {"ehuss"},
+    "rustc-dev-guide": {"spastorino", "amanjeev", "JohnTitor"},
 }
 
 LABELS = {
-    'book': ['C-bug'],
-    'nomicon': ['C-bug'],
-    'reference': ['C-bug'],
-    'rust-by-example': ['C-bug'],
-    'embedded-book': ['C-bug'],
-    'edition-guide': ['C-bug'],
-    'rustc-dev-guide': ['C-bug'],
+    "book": ["C-bug"],
+    "nomicon": ["C-bug"],
+    "reference": ["C-bug"],
+    "rust-by-example": ["C-bug"],
+    "embedded-book": ["C-bug"],
+    "edition-guide": ["C-bug"],
+    "rustc-dev-guide": ["C-bug"],
 }
 
 REPOS = {
-    'book': 'https://github.com/rust-lang/book',
-    'nomicon': 'https://github.com/rust-lang/nomicon',
-    'reference': 'https://github.com/rust-lang/reference',
-    'rust-by-example': 'https://github.com/rust-lang/rust-by-example',
-    'embedded-book': 'https://github.com/rust-embedded/book',
-    'edition-guide': 'https://github.com/rust-lang/edition-guide',
-    'rustc-dev-guide': 'https://github.com/rust-lang/rustc-dev-guide',
+    "book": "https://github.com/rust-lang/book",
+    "nomicon": "https://github.com/rust-lang/nomicon",
+    "reference": "https://github.com/rust-lang/reference",
+    "rust-by-example": "https://github.com/rust-lang/rust-by-example",
+    "embedded-book": "https://github.com/rust-embedded/book",
+    "edition-guide": "https://github.com/rust-lang/edition-guide",
+    "rustc-dev-guide": "https://github.com/rust-lang/rustc-dev-guide",
 }
 
+
 def load_json_from_response(resp):
     # type: (typing.Any) -> typing.Any
     content = resp.read()
     if isinstance(content, bytes):
-        content_str = content.decode('utf-8')
+        content_str = content.decode("utf-8")
     else:
         print("Refusing to decode " + str(type(content)) + " to str")
     return json.loads(content_str)
@@ -70,11 +72,10 @@ def load_json_from_response(resp):
 
 def read_current_status(current_commit, path):
     # type: (str, str) -> typing.Mapping[str, typing.Any]
-    '''Reads build status of `current_commit` from content of `history/*.tsv`
-    '''
-    with open(path, 'r') as f:
+    """Reads build status of `current_commit` from content of `history/*.tsv`"""
+    with open(path, "r") as f:
         for line in f:
-            (commit, status) = line.split('\t', 1)
+            (commit, status) = line.split("\t", 1)
             if commit == current_commit:
                 return json.loads(status)
     return {}
@@ -82,12 +83,12 @@ def read_current_status(current_commit, path):
 
 def gh_url():
     # type: () -> str
-    return os.environ['TOOLSTATE_ISSUES_API_URL']
+    return os.environ["TOOLSTATE_ISSUES_API_URL"]
 
 
 def maybe_remove_mention(message):
     # type: (str) -> str
-    if os.environ.get('TOOLSTATE_SKIP_MENTIONS') is not None:
+    if os.environ.get("TOOLSTATE_SKIP_MENTIONS") is not None:
         return message.replace("@", "")
     return message
 
@@ -102,36 +103,45 @@ def issue(
     github_token,
 ):
     # type: (str, str, typing.Iterable[str], str, str, typing.List[str], str) -> None
-    '''Open an issue about the toolstate failure.'''
-    if status == 'test-fail':
-        status_description = 'has failing tests'
+    """Open an issue about the toolstate failure."""
+    if status == "test-fail":
+        status_description = "has failing tests"
     else:
-        status_description = 'no longer builds'
-    request = json.dumps({
-        'body': maybe_remove_mention(textwrap.dedent('''\
+        status_description = "no longer builds"
+    request = json.dumps(
+        {
+            "body": maybe_remove_mention(
+                textwrap.dedent("""\
         Hello, this is your friendly neighborhood mergebot.
         After merging PR {}, I observed that the tool {} {}.
         A follow-up PR to the repository {} is needed to fix the fallout.
 
         cc @{}, do you think you would have time to do the follow-up work?
         If so, that would be great!
-        ''').format(
-            relevant_pr_number, tool, status_description,
-            REPOS.get(tool), relevant_pr_user
-        )),
-        'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
-        'assignees': list(assignees),
-        'labels': labels,
-    })
-    print("Creating issue:\n{}".format(request))
-    response = urllib2.urlopen(urllib2.Request(
-        gh_url(),
-        request.encode(),
-        {
-            'Authorization': 'token ' + github_token,
-            'Content-Type': 'application/json',
+        """).format(
+                    relevant_pr_number,
+                    tool,
+                    status_description,
+                    REPOS.get(tool),
+                    relevant_pr_user,
+                )
+            ),
+            "title": "`{}` no longer builds after {}".format(tool, relevant_pr_number),
+            "assignees": list(assignees),
+            "labels": labels,
         }
-    ))
+    )
+    print("Creating issue:\n{}".format(request))
+    response = urllib2.urlopen(
+        urllib2.Request(
+            gh_url(),
+            request.encode(),
+            {
+                "Authorization": "token " + github_token,
+                "Content-Type": "application/json",
+            },
+        )
+    )
     response.read()
 
 
@@ -145,27 +155,26 @@ def update_latest(
     github_token,
 ):
     # type: (str, str, str, str, str, str, str) -> str
-    '''Updates `_data/latest.json` to match build result of the given commit.
-    '''
-    with open('_data/latest.json', 'r+') as f:
+    """Updates `_data/latest.json` to match build result of the given commit."""
+    with open("_data/latest.json", "r+") as f:
         latest = json.load(f, object_pairs_hook=collections.OrderedDict)
 
         current_status = {
-            os_: read_current_status(current_commit, 'history/' + os_ + '.tsv')
-            for os_ in ['windows', 'linux']
+            os_: read_current_status(current_commit, "history/" + os_ + ".tsv")
+            for os_ in ["windows", "linux"]
         }
 
-        slug = 'rust-lang/rust'
-        message = textwrap.dedent('''\
+        slug = "rust-lang/rust"
+        message = textwrap.dedent("""\
             📣 Toolstate changed by {}!
 
             Tested on commit {}@{}.
             Direct link to PR: <{}>
 
-        ''').format(relevant_pr_number, slug, current_commit, relevant_pr_url)
+        """).format(relevant_pr_number, slug, current_commit, relevant_pr_url)
         anything_changed = False
         for status in latest:
-            tool = status['tool']
+            tool = status["tool"]
             changed = False
             create_issue_for_status = None  # set to the status that caused the issue
 
@@ -173,57 +182,70 @@ def update_latest(
                 old = status[os_]
                 new = s.get(tool, old)
                 status[os_] = new
-                maintainers = ' '.join('@'+name for name in MAINTAINERS.get(tool, ()))
+                maintainers = " ".join("@" + name for name in MAINTAINERS.get(tool, ()))
                 # comparing the strings, but they are ordered appropriately:
                 # "test-pass" > "test-fail" > "build-fail"
                 if new > old:
                     # things got fixed or at least the status quo improved
                     changed = True
-                    message += '🎉 {} on {}: {} → {} (cc {}).\n' \
-                        .format(tool, os_, old, new, maintainers)
+                    message += "🎉 {} on {}: {} → {} (cc {}).\n".format(
+                        tool, os_, old, new, maintainers
+                    )
                 elif new < old:
                     # tests or builds are failing and were not failing before
                     changed = True
-                    title = '💔 {} on {}: {} → {}' \
-                        .format(tool, os_, old, new)
-                    message += '{} (cc {}).\n' \
-                        .format(title, maintainers)
+                    title = "💔 {} on {}: {} → {}".format(tool, os_, old, new)
+                    message += "{} (cc {}).\n".format(title, maintainers)
                     # See if we need to create an issue.
                     # Create issue if things no longer build.
                     # (No issue for mere test failures to avoid spurious issues.)
-                    if new == 'build-fail':
+                    if new == "build-fail":
                         create_issue_for_status = new
 
             if create_issue_for_status is not None:
                 try:
                     issue(
-                        tool, create_issue_for_status, MAINTAINERS.get(tool, ()),
-                        relevant_pr_number, relevant_pr_user, LABELS.get(tool, []),
+                        tool,
+                        create_issue_for_status,
+                        MAINTAINERS.get(tool, ()),
+                        relevant_pr_number,
+                        relevant_pr_user,
+                        LABELS.get(tool, []),
                         github_token,
                     )
                 except HTTPError as e:
                     # network errors will simply end up not creating an issue, but that's better
                     # than failing the entire build job
-                    print("HTTPError when creating issue for status regression: {0}\n{1!r}"
-                          .format(e, e.read()))
+                    print(
+                        "HTTPError when creating issue for status regression: {0}\n{1!r}".format(
+                            e, e.read()
+                        )
+                    )
                 except IOError as e:
-                    print("I/O error when creating issue for status regression: {0}".format(e))
+                    print(
+                        "I/O error when creating issue for status regression: {0}".format(
+                            e
+                        )
+                    )
                 except:
-                    print("Unexpected error when creating issue for status regression: {0}"
-                          .format(sys.exc_info()[0]))
+                    print(
+                        "Unexpected error when creating issue for status regression: {0}".format(
+                            sys.exc_info()[0]
+                        )
+                    )
                     raise
 
             if changed:
-                status['commit'] = current_commit
-                status['datetime'] = current_datetime
+                status["commit"] = current_commit
+                status["datetime"] = current_datetime
                 anything_changed = True
 
         if not anything_changed:
-            return ''
+            return ""
 
         f.seek(0)
         f.truncate(0)
-        json.dump(latest, f, indent=4, separators=(',', ': '))
+        json.dump(latest, f, indent=4, separators=(",", ": "))
         return message
 
 
@@ -231,12 +253,12 @@ def update_latest(
 # There are variables declared within that are implicitly global; it is unknown
 # which ones precisely but at least this is true for `github_token`.
 try:
-    if __name__ != '__main__':
+    if __name__ != "__main__":
         exit(0)
 
     cur_commit = sys.argv[1]
     cur_datetime = datetime.datetime.now(datetime.timezone.utc).strftime(
-        '%Y-%m-%dT%H:%M:%SZ'
+        "%Y-%m-%dT%H:%M:%SZ"
     )
     cur_commit_msg = sys.argv[2]
     save_message_to_path = sys.argv[3]
@@ -244,21 +266,21 @@ try:
 
     # assume that PR authors are also owners of the repo where the branch lives
     relevant_pr_match = re.search(
-        r'Auto merge of #([0-9]+) - ([^:]+):[^,]+, r=(\S+)',
+        r"Auto merge of #([0-9]+) - ([^:]+):[^,]+, r=(\S+)",
         cur_commit_msg,
     )
     if relevant_pr_match:
         number = relevant_pr_match.group(1)
         relevant_pr_user = relevant_pr_match.group(2)
-        relevant_pr_number = 'rust-lang/rust#' + number
-        relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number
+        relevant_pr_number = "rust-lang/rust#" + number
+        relevant_pr_url = "https://github.com/rust-lang/rust/pull/" + number
         pr_reviewer = relevant_pr_match.group(3)
     else:
-        number = '-1'
-        relevant_pr_user = 'ghost'
-        relevant_pr_number = '<unknown PR>'
-        relevant_pr_url = '<unknown>'
-        pr_reviewer = 'ghost'
+        number = "-1"
+        relevant_pr_user = "ghost"
+        relevant_pr_number = "<unknown PR>"
+        relevant_pr_url = "<unknown>"
+        pr_reviewer = "ghost"
 
     message = update_latest(
         cur_commit,
@@ -270,28 +292,30 @@ try:
         github_token,
     )
     if not message:
-        print('<Nothing changed>')
+        print("<Nothing changed>")
         sys.exit(0)
 
     print(message)
 
     if not github_token:
-        print('Dry run only, not committing anything')
+        print("Dry run only, not committing anything")
         sys.exit(0)
 
-    with open(save_message_to_path, 'w') as f:
+    with open(save_message_to_path, "w") as f:
         f.write(message)
 
     # Write the toolstate comment on the PR as well.
-    issue_url = gh_url() + '/{}/comments'.format(number)
-    response = urllib2.urlopen(urllib2.Request(
-        issue_url,
-        json.dumps({'body': maybe_remove_mention(message)}).encode(),
-        {
-            'Authorization': 'token ' + github_token,
-            'Content-Type': 'application/json',
-        }
-    ))
+    issue_url = gh_url() + "/{}/comments".format(number)
+    response = urllib2.urlopen(
+        urllib2.Request(
+            issue_url,
+            json.dumps({"body": maybe_remove_mention(message)}).encode(),
+            {
+                "Authorization": "token " + github_token,
+                "Content-Type": "application/json",
+            },
+        )
+    )
     response.read()
 except HTTPError as e:
     print("HTTPError: %s\n%r" % (e, e.read()))
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 3c172b2d956..15ed03ad5c2 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 bstr = "1.6.0"
 object = "0.36.2"
 similar = "2.5.0"
-wasmparser = { version = "0.216", default-features = false, features = ["std"] }
+wasmparser = { version = "0.219", default-features = false, features = ["std"] }
 regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
 gimli = "0.31.0"
 build_helper = { path = "../../build_helper" }
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 9e09527d6d0..e73413085fa 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -329,7 +329,7 @@ impl CompletedProcess {
     /// Checks that `stderr` does not contain the regex pattern `unexpected`.
     #[track_caller]
     pub fn assert_stderr_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self {
-        assert_not_contains_regex(&self.stdout_utf8(), unexpected);
+        assert_not_contains_regex(&self.stderr_utf8(), unexpected);
         self
     }
 
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 494daeca963..ffe10092cc2 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -227,6 +227,12 @@ impl Rustc {
         self
     }
 
+    /// Normalize the line number in the stderr output
+    pub fn ui_testing(&mut self) -> &mut Self {
+        self.cmd.arg(format!("-Zui-testing"));
+        self
+    }
+
     /// Specify the target triple, or a path to a custom target json spec file.
     pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
         let target = target.as_ref();
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index 95dfe56ff54..9a7a1a01a09 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -695,7 +695,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
     ),
     rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing),
-    rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
     gated!(
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 266109765ab..b97dfb3b8ef 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
@@ -3936,17 +3936,8 @@ The tracking issue for this feature is: [#117693]
 "##,
     },
     Lint {
-        label: "core_pattern_type",
-        description: r##"# `core_pattern_type`
-
-This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
-
-------------------------
-"##,
-    },
-    Lint {
-        label: "core_pattern_types",
-        description: r##"# `core_pattern_types`
+        label: "pattern_type_macro",
+        description: r##"# `pattern_type_macro`
 
 This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
 
diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
index 660afff3dca..006748ddb08 100644
--- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
@@ -62,15 +62,13 @@ fn memusage_linux() -> MemoryUsage {
     // mallinfo2 is very recent, so its presence needs to be detected at runtime.
     // Both are abysmally slow.
 
-    use std::ffi::CStr;
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static MALLINFO2: AtomicUsize = AtomicUsize::new(1);
 
     let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed);
     if mallinfo2 == 1 {
-        let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap();
-        mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize;
+        mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"mallinfo2".as_ptr()) } as usize;
         // NB: races don't matter here, since they'll always store the same value
         MALLINFO2.store(mallinfo2, Ordering::Relaxed);
     }
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 400eb7c5e0d..e8c9c4f4cd1 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -47,9 +47,9 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.17"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -96,9 +96,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.92"
+version = "1.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
+checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
 
 [[package]]
 name = "autocfg"
@@ -138,9 +138,9 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "1.10.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
+checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22"
 dependencies = [
  "memchr",
  "regex-automata",
@@ -190,9 +190,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.20"
+version = "4.5.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -200,9 +200,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.20"
+version = "4.5.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
 dependencies = [
  "anstream",
  "anstyle",
@@ -213,9 +213,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.36"
+version = "4.5.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2"
+checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01"
 dependencies = [
  "clap",
 ]
@@ -234,9 +234,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
 
 [[package]]
 name = "colorchoice"
@@ -252,9 +252,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.14"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
 dependencies = [
  "libc",
 ]
@@ -312,6 +312,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "doc-comment"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -360,25 +371,25 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "errno"
-version = "0.3.9"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "fastrand"
-version = "2.1.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
+checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
 
 [[package]]
 name = "flate2"
-version = "1.0.34"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -456,9 +467,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.15.0"
+version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 
 [[package]]
 name = "heck"
@@ -525,20 +536,149 @@ dependencies = [
 ]
 
 [[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "idna"
-version = "0.5.0"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
 dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "icu_normalizer",
+ "icu_properties",
 ]
 
 [[package]]
 name = "indexmap"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -552,16 +692,17 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 
 [[package]]
 name = "itoa"
-version = "1.0.11"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
 
 [[package]]
 name = "js-sys"
-version = "0.3.72"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
+checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705"
 dependencies = [
+ "once_cell",
  "wasm-bindgen",
 ]
 
@@ -573,9 +714,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.161"
+version = "0.2.167"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
 
 [[package]]
 name = "libdbus-sys"
@@ -603,6 +744,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
 [[package]]
+name = "litemap"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+
+[[package]]
 name = "lock_api"
 version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -646,9 +793,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.42"
+version = "0.4.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3"
+checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -709,31 +856,21 @@ dependencies = [
 ]
 
 [[package]]
-name = "mdbook-trpl-listing"
+name = "mdbook-trpl"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
  "clap",
  "html_parser",
  "mdbook",
- "pulldown-cmark 0.10.3",
- "pulldown-cmark-to-cmark 13.0.0",
+ "pulldown-cmark 0.12.2",
+ "pulldown-cmark-to-cmark 19.0.0",
  "serde_json",
  "thiserror",
  "toml 0.8.19",
 ]
 
 [[package]]
-name = "mdbook-trpl-note"
-version = "1.0.0"
-dependencies = [
- "clap",
- "mdbook",
- "pulldown-cmark 0.10.3",
- "pulldown-cmark-to-cmark 13.0.0",
- "serde_json",
-]
-
-[[package]]
 name = "memchr"
 version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -852,9 +989,9 @@ dependencies = [
 
 [[package]]
 name = "pathdiff"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361"
+checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
 
 [[package]]
 name = "percent-encoding"
@@ -996,9 +1133,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.89"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
 dependencies = [
  "unicode-ident",
 ]
@@ -1010,7 +1147,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
 dependencies = [
  "bitflags 2.6.0",
- "getopts",
  "memchr",
  "pulldown-cmark-escape 0.10.1",
  "unicase",
@@ -1029,6 +1165,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "pulldown-cmark"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
+dependencies = [
+ "bitflags 2.6.0",
+ "getopts",
+ "memchr",
+ "pulldown-cmark-escape 0.11.0",
+ "unicase",
+]
+
+[[package]]
 name = "pulldown-cmark-escape"
 version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1042,20 +1191,20 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
 
 [[package]]
 name = "pulldown-cmark-to-cmark"
-version = "13.0.0"
+version = "15.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b"
+checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1"
 dependencies = [
- "pulldown-cmark 0.10.3",
+ "pulldown-cmark 0.11.3",
 ]
 
 [[package]]
 name = "pulldown-cmark-to-cmark"
-version = "15.0.1"
+version = "19.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1"
+checksum = "7d742adcc7b655dba3e9ebab47954ca229fc0fa1df01fdc94349b6f3a2e6d257"
 dependencies = [
- "pulldown-cmark 0.11.3",
+ "pulldown-cmark 0.12.2",
 ]
 
 [[package]]
@@ -1120,9 +1269,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1144,15 +1293,14 @@ dependencies = [
  "mdbook",
  "mdbook-i18n-helpers",
  "mdbook-spec",
- "mdbook-trpl-listing",
- "mdbook-trpl-note",
+ "mdbook-trpl",
 ]
 
 [[package]]
 name = "rustix"
-version = "0.38.38"
+version = "0.38.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
+checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
 dependencies = [
  "bitflags 2.6.0",
  "errno",
@@ -1190,18 +1338,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
 
 [[package]]
 name = "serde"
-version = "1.0.214"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.214"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1210,9 +1358,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.132"
+version = "1.0.133"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
 dependencies = [
  "itoa",
  "memchr",
@@ -1259,6 +1407,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
 name = "string_cache"
 version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1292,9 +1446,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "syn"
-version = "2.0.87"
+version = "2.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1302,6 +1456,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "syntect"
 version = "5.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1323,9 +1488,9 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.13.0"
+version = "3.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
+checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
 dependencies = [
  "cfg-if",
  "fastrand",
@@ -1347,9 +1512,9 @@ dependencies = [
 
 [[package]]
 name = "terminal_size"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
+checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
 dependencies = [
  "rustix",
  "windows-sys 0.59.0",
@@ -1363,18 +1528,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
 
 [[package]]
 name = "thiserror"
-version = "1.0.66"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.66"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1382,21 +1547,16 @@ dependencies = [
 ]
 
 [[package]]
-name = "tinyvec"
-version = "1.8.0"
+name = "tinystr"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
 dependencies = [
- "tinyvec_macros",
+ "displaydoc",
+ "zerovec",
 ]
 
 [[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
-[[package]]
 name = "toml"
 version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1464,25 +1624,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
 
 [[package]]
-name = "unicode-bidi"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
-
-[[package]]
 name = "unicode-ident"
-version = "1.0.13"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
-dependencies = [
- "tinyvec",
-]
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
 
 [[package]]
 name = "unicode-width"
@@ -1492,9 +1637,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
 [[package]]
 name = "url"
-version = "2.5.2"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -1508,6 +1653,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
 name = "utf8parse"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1537,9 +1694,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
+checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -1548,9 +1705,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
+checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd"
 dependencies = [
  "bumpalo",
  "log",
@@ -1563,9 +1720,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
+checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1573,9 +1730,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
+checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1586,9 +1743,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
+checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49"
 
 [[package]]
 name = "winapi"
@@ -1722,6 +1879,42 @@ dependencies = [
 ]
 
 [[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
 name = "zerocopy"
 version = "0.7.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1741,3 +1934,46 @@ dependencies = [
  "quote",
  "syn",
 ]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 854c4547337..c2ce8fef4d0 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -9,8 +9,7 @@ edition = "2021"
 [dependencies]
 clap = "4.0.32"
 env_logger = "0.11"
-mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" }
-mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" }
+mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" }
 mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index a1ef18610b0..33f2a51215d 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -6,8 +6,7 @@ use mdbook::MDBook;
 use mdbook::errors::Result as Result3;
 use mdbook_i18n_helpers::preprocessors::Gettext;
 use mdbook_spec::Spec;
-use mdbook_trpl_listing::TrplListing;
-use mdbook_trpl_note::TrplNote;
+use mdbook_trpl::{Figure, Listing, Note};
 
 fn main() {
     let crate_version = concat!("v", crate_version!());
@@ -109,11 +108,15 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
     // preprocessor, or this should modify the config and use
     // MDBook::load_with_config.
     if book.config.get_preprocessor("trpl-note").is_some() {
-        book.with_preprocessor(TrplNote);
+        book.with_preprocessor(Note);
     }
 
     if book.config.get_preprocessor("trpl-listing").is_some() {
-        book.with_preprocessor(TrplListing);
+        book.with_preprocessor(Listing);
+    }
+
+    if book.config.get_preprocessor("trpl-figure").is_some() {
+        book.with_preprocessor(Figure);
     }
 
     if book.config.get_preprocessor("spec").is_some() {
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 54ad56ed3f3..63cc8794cea 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination};
+use rustc_errors::registry::Registry;
 use rustc_errors::translation::Translate;
 use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
@@ -38,10 +39,10 @@ struct SilentOnIgnoredFilesEmitter {
 }
 
 impl SilentOnIgnoredFilesEmitter {
-    fn handle_non_ignoreable_error(&mut self, diag: DiagInner) {
+    fn handle_non_ignoreable_error(&mut self, diag: DiagInner, registry: &Registry) {
         self.has_non_ignorable_parser_errors = true;
         self.can_reset.store(false, Ordering::Release);
-        self.emitter.emit_diagnostic(diag);
+        self.emitter.emit_diagnostic(diag, registry);
     }
 }
 
@@ -60,9 +61,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
         None
     }
 
-    fn emit_diagnostic(&mut self, diag: DiagInner) {
+    fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry) {
         if diag.level() == DiagnosticLevel::Fatal {
-            return self.handle_non_ignoreable_error(diag);
+            return self.handle_non_ignoreable_error(diag, registry);
         }
         if let Some(primary_span) = &diag.span.primary_span() {
             let file_name = self.source_map.span_to_filename(*primary_span);
@@ -80,7 +81,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
                 }
             };
         }
-        self.handle_non_ignoreable_error(diag);
+        self.handle_non_ignoreable_error(diag, registry);
     }
 }
 
@@ -358,7 +359,7 @@ mod tests {
                 None
             }
 
-            fn emit_diagnostic(&mut self, _diag: DiagInner) {
+            fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {
                 self.num_emitted_errors.fetch_add(1, Ordering::Release);
             }
         }
@@ -412,6 +413,7 @@ mod tests {
                 SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
                 source,
             );
+            let registry = Registry::new(&[]);
             let mut emitter = build_emitter(
                 Lrc::clone(&num_emitted_errors),
                 Lrc::clone(&can_reset_errors),
@@ -420,7 +422,7 @@ mod tests {
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
             let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span));
-            emitter.emit_diagnostic(fatal_diagnostic);
+            emitter.emit_diagnostic(fatal_diagnostic, &registry);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
@@ -437,6 +439,7 @@ mod tests {
                 SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
                 source,
             );
+            let registry = Registry::new(&[]);
             let mut emitter = build_emitter(
                 Lrc::clone(&num_emitted_errors),
                 Lrc::clone(&can_reset_errors),
@@ -445,7 +448,7 @@ mod tests {
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
             let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
-            emitter.emit_diagnostic(non_fatal_diagnostic);
+            emitter.emit_diagnostic(non_fatal_diagnostic, &registry);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
         }
@@ -461,6 +464,7 @@ mod tests {
                 SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
                 source,
             );
+            let registry = Registry::new(&[]);
             let mut emitter = build_emitter(
                 Lrc::clone(&num_emitted_errors),
                 Lrc::clone(&can_reset_errors),
@@ -469,7 +473,7 @@ mod tests {
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
             let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
-            emitter.emit_diagnostic(non_fatal_diagnostic);
+            emitter.emit_diagnostic(non_fatal_diagnostic, &registry);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
@@ -497,6 +501,7 @@ mod tests {
                 SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("fatal.rs"))),
                 fatal_source,
             );
+            let registry = Registry::new(&[]);
             let mut emitter = build_emitter(
                 Lrc::clone(&num_emitted_errors),
                 Lrc::clone(&can_reset_errors),
@@ -508,9 +513,9 @@ mod tests {
             let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span));
             let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span));
             let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None);
-            emitter.emit_diagnostic(bar_diagnostic);
-            emitter.emit_diagnostic(foo_diagnostic);
-            emitter.emit_diagnostic(fatal_diagnostic);
+            emitter.emit_diagnostic(bar_diagnostic, &registry);
+            emitter.emit_diagnostic(foo_diagnostic, &registry);
+            emitter.emit_diagnostic(fatal_diagnostic, &registry);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 6fe2d4a8520..7b4730eadc8 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -48,7 +48,8 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
         | ast::PatKind::MacCall(..)
         | ast::PatKind::Slice(..)
         | ast::PatKind::Path(..)
-        | ast::PatKind::Range(..) => false,
+        | ast::PatKind::Range(..)
+        | ast::PatKind::Guard(..) => false,
         ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1,
         ast::PatKind::TupleStruct(_, ref path, ref subpats) => {
             path.segments.len() <= 1 && subpats.len() <= 1
@@ -338,8 +339,9 @@ impl Rewrite for Pat {
                         .max_width_error(shape.width, self.span)?,
                 )
                 .map(|inner_pat| format!("({})", inner_pat)),
-            PatKind::Err(_) => Err(RewriteError::Unknown),
+            PatKind::Guard(..) => Ok(context.snippet(self.span).to_string()),
             PatKind::Deref(_) => Err(RewriteError::Unknown),
+            PatKind::Err(_) => Err(RewriteError::Unknown),
         }
     }
 }
diff --git a/src/tools/rustfmt/tests/target/guard_patterns.rs b/src/tools/rustfmt/tests/target/guard_patterns.rs
new file mode 100644
index 00000000000..2e4667b916c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/guard_patterns.rs
@@ -0,0 +1,12 @@
+#![feature(guard_patterns)]
+
+fn main() {
+    match user.subscription_plan() {
+        (Plan::Regular if user.credit() >= 100) | (Plan::Premium if user.credit() >= 80) => {
+            // Complete the transaction.
+        }
+        _ => {
+            // The user doesn't have enough credit, return an error message.
+        }
+    }
+}
diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml
deleted file mode 100644
index d5b8b198afb..00000000000
--- a/src/tools/tidy/config/black.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[tool.black]
-# Ignore all submodules
-extend-exclude = """(\
-    src/doc/nomicon|\
-    src/tools/cargo/|\
-    src/doc/reference/|\
-    src/doc/book/|\
-    src/doc/rust-by-example/|\
-    library/stdarch/|\
-    src/doc/rustc-dev-guide/|\
-    src/doc/edition-guide/|\
-    src/llvm-project/|\
-    src/doc/embedded-book/|\
-    src/tools/rustc-perf/|\
-    src/tools/enzyme/|\
-    library/backtrace/|\
-    src/gcc/
-    )"""
diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in
index 8938dc03243..1b2c38f2b5d 100644
--- a/src/tools/tidy/config/requirements.in
+++ b/src/tools/tidy/config/requirements.in
@@ -6,6 +6,5 @@
 # Note: this generation step should be run with the oldest supported python
 # version (currently 3.9) to ensure backward compatibility
 
-black==24.4.2
 ruff==0.4.9
 clang-format==18.1.7
diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt
index 790eabf5cf8..938179d5b3e 100644
--- a/src/tools/tidy/config/requirements.txt
+++ b/src/tools/tidy/config/requirements.txt
@@ -4,30 +4,6 @@
 #
 #    pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in
 #
-black==24.4.2 \
-    --hash=sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 \
-    --hash=sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1 \
-    --hash=sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0 \
-    --hash=sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8 \
-    --hash=sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96 \
-    --hash=sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 \
-    --hash=sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04 \
-    --hash=sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021 \
-    --hash=sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94 \
-    --hash=sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d \
-    --hash=sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c \
-    --hash=sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7 \
-    --hash=sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c \
-    --hash=sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc \
-    --hash=sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7 \
-    --hash=sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d \
-    --hash=sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c \
-    --hash=sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741 \
-    --hash=sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce \
-    --hash=sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb \
-    --hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \
-    --hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e
-    # via -r src/tools/tidy/config/requirements.in
 clang-format==18.1.7 \
     --hash=sha256:035204410f65d03f98cb81c9c39d6d193f9987917cc88de9d0dbd01f2aa9c302 \
     --hash=sha256:05c482a854287a5d21f7567186c0bd4b8dbd4a871751e655a45849185f30b931 \
@@ -45,26 +21,6 @@ clang-format==18.1.7 \
     --hash=sha256:f4f77ac0f4f9a659213fedda0f2d216886c410132e6e7dd4b13f92b34e925554 \
     --hash=sha256:f935d34152a2e11e55120eb9182862f432bc9789ab819f680c9f6db4edebf9e3
     # via -r src/tools/tidy/config/requirements.in
-click==8.1.3 \
-    --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
-    --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
-    # via black
-mypy-extensions==1.0.0 \
-    --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
-    --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
-    # via black
-packaging==23.1 \
-    --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \
-    --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f
-    # via black
-pathspec==0.11.1 \
-    --hash=sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687 \
-    --hash=sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293
-    # via black
-platformdirs==4.2.2 \
-    --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \
-    --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3
-    # via black
 ruff==0.4.9 \
     --hash=sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893 \
     --hash=sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff \
@@ -84,11 +40,3 @@ ruff==0.4.9 \
     --hash=sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde \
     --hash=sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3
     # via -r src/tools/tidy/config/requirements.in
-tomli==2.0.1 \
-    --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
-    --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
-    # via black
-typing-extensions==4.12.2 \
-    --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
-    --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
-    # via black
diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml
index de23d93593c..4a5aa618be1 100644
--- a/src/tools/tidy/config/ruff.toml
+++ b/src/tools/tidy/config/ruff.toml
@@ -19,6 +19,9 @@ extend-exclude = [
     "src/tools/enzyme/",
     "src/tools/rustc-perf/",
     "src/gcc/",
+    "compiler/rustc_codegen_gcc",
+    "src/tools/clippy",
+    "src/tools/miri",
     # Hack: CI runs from a subdirectory under the main checkout
     "../src/doc/nomicon/",
     "../src/tools/cargo/",
@@ -34,6 +37,9 @@ extend-exclude = [
     "../src/tools/enzyme/",
     "../src/tools/rustc-perf/",
     "../src/gcc/",
+    "../compiler/rustc_codegen_gcc",
+    "../src/tools/clippy",
+    "../src/tools/miri",
 ]
 
 [lint]
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e065f01ebba..beeb33b46ff 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -12,7 +12,8 @@ use cargo_metadata::{Metadata, Package, PackageId};
 #[rustfmt::skip]
 const LICENSES: &[&str] = &[
     // tidy-alphabetical-start
-    "(MIT OR Apache-2.0) AND Unicode-DFS-2016",            // unicode_ident
+    "(MIT OR Apache-2.0) AND Unicode-3.0",                 // unicode_ident (1.0.14)
+    "(MIT OR Apache-2.0) AND Unicode-DFS-2016",            // unicode_ident (1.0.12)
     "0BSD OR MIT OR Apache-2.0",                           // adler license
     "0BSD",
     "Apache-2.0 / MIT",
@@ -94,7 +95,6 @@ const EXCEPTIONS: ExceptionList = &[
     ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
     ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
     ("foldhash", "Zlib"),                                    // rustc
-    ("instant", "BSD-3-Clause"),                             // rustc_driver/tracing-subscriber/parking_lot
     ("mdbook", "MPL-2.0"),                                   // mdbook
     ("option-ext", "MPL-2.0"),                               // cargo-miri (via `directories`)
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),     // rustc (license is the same as LLVM uses)
@@ -307,7 +307,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "intl_pluralrules",
     "itertools",
     "itoa",
-    "jemalloc-sys",
     "jobserver",
     "lazy_static",
     "leb128",
@@ -392,6 +391,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "thiserror-impl",
     "thorin-dwp",
     "thread_local",
+    "tikv-jemalloc-sys",
     "time",
     "time-core",
     "time-macros",
@@ -535,6 +535,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "regalloc2",
     "region",
     "rustc-hash",
+    "serde",
+    "serde_derive",
     "slice-group-by",
     "smallvec",
     "stable_deref_trait",
diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs
index 8f21338c7db..9792650d37d 100644
--- a/src/tools/tidy/src/ext_tool_checks.rs
+++ b/src/tools/tidy/src/ext_tool_checks.rs
@@ -32,9 +32,8 @@ const REL_PY_PATH: &[&str] = &["Scripts", "python3.exe"];
 const REL_PY_PATH: &[&str] = &["bin", "python3"];
 
 const RUFF_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "ruff.toml"];
-const BLACK_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "black.toml"];
 /// Location within build directory
-const RUFF_CACH_PATH: &[&str] = &["cache", "ruff_cache"];
+const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"];
 const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"];
 
 pub fn check(
@@ -96,7 +95,7 @@ fn check_impl(
         let mut cfg_path = root_path.to_owned();
         cfg_path.extend(RUFF_CONFIG_PATH);
         let mut cache_dir = outdir.to_owned();
-        cache_dir.extend(RUFF_CACH_PATH);
+        cache_dir.extend(RUFF_CACHE_PATH);
 
         cfg_args_ruff.extend([
             "--config".as_ref(),
@@ -124,33 +123,36 @@ fn check_impl(
     }
 
     if python_fmt {
-        let mut cfg_args_black = cfg_args.clone();
-        let mut file_args_black = file_args.clone();
+        let mut cfg_args_ruff = cfg_args.clone();
+        let mut file_args_ruff = file_args.clone();
 
         if bless {
             eprintln!("formatting python files");
         } else {
             eprintln!("checking python file formatting");
-            cfg_args_black.push("--check".as_ref());
+            cfg_args_ruff.push("--check".as_ref());
         }
 
         let mut cfg_path = root_path.to_owned();
-        cfg_path.extend(BLACK_CONFIG_PATH);
+        cfg_path.extend(RUFF_CONFIG_PATH);
+        let mut cache_dir = outdir.to_owned();
+        cache_dir.extend(RUFF_CACHE_PATH);
 
-        cfg_args_black.extend(["--config".as_ref(), cfg_path.as_os_str()]);
+        cfg_args_ruff.extend(["--config".as_ref(), cfg_path.as_os_str()]);
 
-        if file_args_black.is_empty() {
-            file_args_black.push(root_path.as_os_str());
+        if file_args_ruff.is_empty() {
+            file_args_ruff.push(root_path.as_os_str());
         }
 
-        let mut args = merge_args(&cfg_args_black, &file_args_black);
-        let res = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args);
+        let mut args = merge_args(&cfg_args_ruff, &file_args_ruff);
+        args.insert(0, "format".as_ref());
+        let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args);
 
         if res.is_err() && show_diff {
             eprintln!("\npython formatting does not match! Printing diff:");
 
             args.insert(0, "--diff".as_ref());
-            let _ = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args);
+            let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args);
         }
         // Rethrow error
         let _ = res?;
@@ -445,7 +447,7 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> {
     }
 
     let status = Command::new("shellcheck").args(args).status()?;
-    if status.success() { Ok(()) } else { Err(Error::FailedCheck("black")) }
+    if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) }
 }
 
 /// Check git for tracked files matching an extension
diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs
index 8bc404dc858..6a136e5aec6 100644
--- a/src/tools/tidy/src/fluent_period.rs
+++ b/src/tools/tidy/src/fluent_period.rs
@@ -18,7 +18,6 @@ const ALLOWLIST: &[&str] = &[
     "const_eval_validation_failure_note",
     "driver_impl_ice",
     "incremental_corrupt_file",
-    "mir_build_pointer_pattern",
 ];
 
 fn check_period(filename: &str, contents: &str, bad: &mut bool) {
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index ac82a17e145..25cd32063aa 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -510,7 +510,6 @@ ui/confuse-field-and-method/issue-2392.rs
 ui/confuse-field-and-method/issue-32128.rs
 ui/confuse-field-and-method/issue-33784.rs
 ui/const-generics/generic_arg_infer/issue-91614.rs
-ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs
 ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
 ui/const-generics/generic_const_exprs/issue-100217.rs
 ui/const-generics/generic_const_exprs/issue-100360.rs
@@ -540,7 +539,6 @@ ui/const-generics/generic_const_exprs/issue-85848.rs
 ui/const-generics/generic_const_exprs/issue-86710.rs
 ui/const-generics/generic_const_exprs/issue-89851.rs
 ui/const-generics/generic_const_exprs/issue-90847.rs
-ui/const-generics/generic_const_exprs/issue-94287.rs
 ui/const-generics/generic_const_exprs/issue-94293.rs
 ui/const-generics/generic_const_exprs/issue-96699.rs
 ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
@@ -2297,8 +2295,6 @@ ui/issues/issue-43853.rs
 ui/issues/issue-4387.rs
 ui/issues/issue-43910.rs
 ui/issues/issue-43923.rs
-ui/issues/issue-43925.rs
-ui/issues/issue-43926.rs
 ui/issues/issue-43988.rs
 ui/issues/issue-44023.rs
 ui/issues/issue-44056.rs
@@ -2547,8 +2543,6 @@ ui/issues/issue-6936.rs
 ui/issues/issue-69455.rs
 ui/issues/issue-69602-type-err-during-codegen-ice.rs
 ui/issues/issue-69683.rs
-ui/issues/issue-70093/issue-70093-link-directives.rs
-ui/issues/issue-70093/issue-70093.rs
 ui/issues/issue-7012.rs
 ui/issues/issue-70381.rs
 ui/issues/issue-7044.rs
@@ -2713,11 +2707,15 @@ ui/limits/issue-17913.rs
 ui/limits/issue-55878.rs
 ui/limits/issue-69485-var-size-diffs-too-large.rs
 ui/limits/issue-75158-64.rs
+ui/link-native-libs/issue-109144.rs
+ui/link-native-libs/issue-43925.rs
+ui/link-native-libs/issue-43926.rs
+ui/link-native-libs/issue-70093/issue-70093-link-directives.rs
+ui/link-native-libs/issue-70093/issue-70093.rs
 ui/linkage-attr/auxiliary/issue-12133-dylib.rs
 ui/linkage-attr/auxiliary/issue-12133-dylib2.rs
 ui/linkage-attr/auxiliary/issue-12133-rlib.rs
 ui/linkage-attr/issue-10755.rs
-ui/linkage-attr/issue-109144.rs
 ui/linkage-attr/issue-12133-1.rs
 ui/linkage-attr/issue-12133-2.rs
 ui/linkage-attr/issue-12133-3.rs
@@ -3481,8 +3479,6 @@ ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs
 ui/pattern/usefulness/issue-82772-match-box-as-struct.rs
 ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs
 ui/pattern/usefulness/issue-88747.rs
-ui/polymorphization/issue-74614.rs
-ui/polymorphization/issue-74636.rs
 ui/privacy/auxiliary/issue-117997.rs
 ui/privacy/auxiliary/issue-119463-extern.rs
 ui/privacy/auxiliary/issue-17718-const-privacy.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 11f9d5bb03d..401169c838f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -17,7 +17,7 @@ use ignore::Walk;
 const ENTRY_LIMIT: u32 = 901;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: u32 = 1672;
+const ISSUES_ENTRY_LIMIT: u32 = 1667;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs
index 14da876eda7..9a51979a2f0 100644
--- a/src/tools/unicode-table-generator/src/range_search.rs
+++ b/src/tools/unicode-table-generator/src/range_search.rs
@@ -1,5 +1,4 @@
 #[inline(always)]
-#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]
 const fn bitset_search<
     const N: usize,
     const CHUNK_SIZE: usize,
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index dd064c59283..46010692fe5 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -97,10 +97,6 @@ impl RawEmitter {
 
         self.blank_line();
 
-        writeln!(
-            &mut self.file,
-            r#"#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]"#
-        ).unwrap();
         writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
         if first_code_point > 0x7f {
             writeln!(&mut self.file, "    (c as u32) >= {first_code_point:#04x} &&").unwrap();
diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index acdb1aa1ab7..965e9b01a44 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@ name = "wasm-component-ld"
 path = "src/main.rs"
 
 [dependencies]
-wasm-component-ld = "0.5.10"
+wasm-component-ld = "0.5.11"