about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock77
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml12
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/bench.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/main.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/path.rs41
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs18
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt1
-rw-r--r--compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs17
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch4
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch7
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch23
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh3
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh17
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh3
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs51
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs27
-rw-r--r--compiler/rustc_codegen_cranelift/src/codegen_i128.rs27
-rw-r--r--compiler/rustc_codegen_cranelift/src/config.rs80
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs276
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs29
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs59
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs5
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt1
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs6
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs46
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs34
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs15
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs19
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs9
-rw-r--r--compiler/rustc_middle/src/query/mod.rs17
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs126
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs114
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs5
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/check_tail_calls.rs386
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs24
-rw-r--r--compiler/rustc_monomorphize/messages.ftl2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs6
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs25
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs21
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs334
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs8
-rw-r--r--compiler/rustc_session/messages.ftl1
-rw-r--r--compiler/rustc_session/src/errors.rs4
-rw-r--r--compiler/rustc_session/src/options.rs5
-rw-r--r--compiler/rustc_session/src/session.rs5
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs12
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs4
-rw-r--r--compiler/rustc_target/src/callconv/x86.rs3
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs9
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs49
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs3
-rw-r--r--compiler/rustc_type_ir/src/interner.rs3
-rw-r--r--library/alloc/src/fmt.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/string.rs3
-rw-r--r--library/alloc/src/task.rs1
-rw-r--r--library/alloc/src/vec/mod.rs25
-rw-r--r--library/core/src/fmt/float.rs6
-rw-r--r--library/core/src/fmt/mod.rs411
-rw-r--r--library/core/src/iter/traits/collect.rs239
-rw-r--r--library/core/src/task/wake.rs13
-rwxr-xr-xlibrary/core/src/unicode/printable.py53
-rw-r--r--library/core/tests/fmt/mod.rs24
-rw-r--r--library/core/tests/iter/traits/iterator.rs13
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/std/src/io/error.rs18
-rw-r--r--library/std/src/io/error/repr_bitpacked.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/sys/pal/teeos/mod.rs2
-rw-r--r--library/std/src/sys/pal/unix/mod.rs2
-rw-r--r--library/std/src/sys/pal/windows/mod.rs4
-rw-r--r--src/bootstrap/bootstrap.py663
-rw-r--r--src/bootstrap/bootstrap_test.py42
-rwxr-xr-xsrc/bootstrap/configure.py519
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs37
-rwxr-xr-xsrc/ci/cpu-usage-over-time.py36
-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
-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.yml55
-rw-r--r--src/ci/scripts/upload-build-metrics.py21
m---------src/doc/book0
-rw-r--r--src/doc/unstable-book/src/compiler-flags/reg-struct-return.md15
-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_providers.py186
-rw-r--r--src/etc/rust_types.py3
-rw-r--r--src/librustdoc/clean/types.rs13
-rw-r--r--src/librustdoc/html/markdown.rs96
-rw-r--r--src/librustdoc/html/markdown/footnotes.rs25
-rw-r--r--src/librustdoc/html/render/mod.rs45
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css33
m---------src/tools/cargo0
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs10
-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/mod.rs4
-rw-r--r--src/tools/miri/src/machine.rs7
-rw-r--r--src/tools/miri/src/shims/io_error.rs2
-rw-r--r--src/tools/miri/src/shims/native_lib.rs50
-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.rs208
-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/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/dyn-star.rs1
-rw-r--r--src/tools/miri/tests/pass/future-self-referential.rs1
-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/ui.rs1
-rwxr-xr-xsrc/tools/publish_toolstate.py226
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs1
-rw-r--r--src/tools/rustbook/Cargo.lock47
-rw-r--r--src/tools/rustbook/Cargo.toml3
-rw-r--r--src/tools/rustbook/src/main.rs11
-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.rs2
-rw-r--r--src/tools/tidy/src/ext_tool_checks.rs30
-rw-r--r--src/tools/tidy/src/issues.txt4
-rw-r--r--tests/codegen-units/item-collection/static-init.rs4
-rw-r--r--tests/codegen-units/item-collection/trait-method-default-impl.rs4
-rw-r--r--tests/codegen-units/polymorphization/auxiliary/poly-dep.rs4
-rw-r--r--tests/codegen-units/polymorphization/poly-foreign.rs11
-rw-r--r--tests/codegen-units/polymorphization/unused_type_parameters.rs315
-rw-r--r--tests/codegen/emcripten-catch-unwind.rs2
-rw-r--r--tests/codegen/issues/issue-118306.rs2
-rw-r--r--tests/codegen/issues/issue-122805.rs14
-rw-r--r--tests/codegen/reg-struct-return.rs206
-rw-r--r--tests/codegen/slice-iter-nonnull.rs12
-rw-r--r--tests/coverage/async.cov-map100
-rw-r--r--tests/coverage/async.coverage1
-rw-r--r--tests/coverage/async.rs1
-rw-r--r--tests/coverage/async2.cov-map24
-rw-r--r--tests/coverage/async2.coverage1
-rw-r--r--tests/coverage/async2.rs1
-rw-r--r--tests/coverage/async_block.cov-map8
-rw-r--r--tests/coverage/async_block.coverage1
-rw-r--r--tests/coverage/async_block.rs1
-rw-r--r--tests/coverage/auxiliary/executor.rs2
-rw-r--r--tests/coverage/await_ready.cov-map8
-rw-r--r--tests/coverage/await_ready.coverage1
-rw-r--r--tests/coverage/await_ready.rs1
-rw-r--r--tests/coverage/closure_macro_async.cov-map16
-rw-r--r--tests/coverage/closure_macro_async.coverage1
-rw-r--r--tests/coverage/closure_macro_async.rs1
-rw-r--r--tests/crashes/105249.rs16
-rw-r--r--tests/crashes/123809.rs4
-rw-r--r--tests/crashes/123893.rs24
-rw-r--r--tests/crashes/124020.rs33
-rw-r--r--tests/crashes/124436.rs7
-rw-r--r--tests/crashes/130425.rs13
-rw-r--r--tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py3
-rw-r--r--tests/debuginfo/embedded-visualizer-point.py3
-rw-r--r--tests/debuginfo/embedded-visualizer.py3
-rw-r--r--tests/mir-opt/async_closure_shims.rs2
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff8
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff8
-rw-r--r--tests/run-make/missing-unstable-trait-bound/missing-bound.rs4
-rw-r--r--tests/run-make/missing-unstable-trait-bound/missing-bound.stderr12
-rw-r--r--tests/run-make/missing-unstable-trait-bound/rmake.rs24
-rw-r--r--tests/rustdoc-gui/docblock-table-overflow.goml10
-rw-r--r--tests/rustdoc-gui/impl-block-doc.goml42
-rw-r--r--tests/rustdoc-gui/impl-doc.goml2
-rw-r--r--tests/rustdoc-gui/item-info-overflow.goml2
-rw-r--r--tests/rustdoc-gui/source-code-page-code-scroll.goml4
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs39
-rw-r--r--tests/rustdoc-ui/issues/issue-96287.stderr4
-rw-r--r--tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr4
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr6
-rw-r--r--tests/ui/associated-types/associated-types-no-suitable-bound.stderr4
-rw-r--r--tests/ui/associated-types/defaults-suitability.current.stderr4
-rw-r--r--tests/ui/associated-types/defaults-suitability.next.stderr4
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-6.stderr2
-rw-r--r--tests/ui/associated-types/issue-27675-unchecked-bounds.stderr2
-rw-r--r--tests/ui/associated-types/issue-43784-associated-type.stderr2
-rw-r--r--tests/ui/associated-types/issue-59324.stderr8
-rw-r--r--tests/ui/async-await/async-closures/auxiliary/block-on.rs2
-rw-r--r--tests/ui/async-await/async-closures/inline-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/mangle.rs2
-rw-r--r--tests/ui/async-await/async-drop.rs2
-rw-r--r--tests/ui/async-await/async-fn/auxiliary/block-on.rs2
-rw-r--r--tests/ui/async-await/for-await-consumes-iter.rs2
-rw-r--r--tests/ui/async-await/for-await-passthrough.rs3
-rw-r--r--tests/ui/async-await/for-await.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs1
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr8
-rw-r--r--tests/ui/async-await/issue-70818.stderr2
-rw-r--r--tests/ui/async-await/issue-86507.stderr2
-rw-r--r--tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr2
-rw-r--r--tests/ui/binop/binop-consume-args.stderr40
-rw-r--r--tests/ui/binop/binop-move-semantics.stderr4
-rw-r--r--tests/ui/binop/issue-93927.stderr2
-rw-r--r--tests/ui/borrowck/clone-on-ref.stderr4
-rw-r--r--tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr2
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr4
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr2
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr2
-rw-r--r--tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr4
-rw-r--r--tests/ui/closures/closure-bounds-subtype.stderr2
-rw-r--r--tests/ui/closures/issue-67123.stderr2
-rw-r--r--tests/ui/codegen/target-cpus.rs6
-rw-r--r--tests/ui/coherence/fuzzing/best-obligation-ICE.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs21
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-94287.rs10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-94287.stderr15
-rw-r--r--tests/ui/const-generics/issues/issue-61336-2.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-61336.stderr2
-rw-r--r--tests/ui/consts/ct-var-in-collect_all_mismatches.stderr2
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr12
-rw-r--r--tests/ui/consts/unstable-const-fn-in-libcore.stderr4
-rw-r--r--tests/ui/coroutine/async-gen-yield-ty-is-unit.rs2
-rw-r--r--tests/ui/coroutine/async_gen_fn_iter.rs1
-rw-r--r--tests/ui/coroutine/polymorphize-args.rs18
-rw-r--r--tests/ui/dropck/explicit-drop-bounds.bad1.stderr4
-rw-r--r--tests/ui/dropck/explicit-drop-bounds.bad2.stderr4
-rw-r--r--tests/ui/dyn-star/dispatch-on-pin-mut.rs1
-rw-r--r--tests/ui/error-codes/E0229.stderr4
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr30
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr28
-rw-r--r--tests/ui/explicit-tail-calls/become-macro.rs13
-rw-r--r--tests/ui/explicit-tail-calls/become-operator.fixed42
-rw-r--r--tests/ui/explicit-tail-calls/become-operator.rs42
-rw-r--r--tests/ui/explicit-tail-calls/become-operator.stderr75
-rw-r--r--tests/ui/explicit-tail-calls/become-outside.rs2
-rw-r--r--tests/ui/explicit-tail-calls/become-uncallable.fixed18
-rw-r--r--tests/ui/explicit-tail-calls/become-uncallable.rs18
-rw-r--r--tests/ui/explicit-tail-calls/become-uncallable.stderr44
-rw-r--r--tests/ui/explicit-tail-calls/closure.fixed31
-rw-r--r--tests/ui/explicit-tail-calls/closure.rs31
-rw-r--r--tests/ui/explicit-tail-calls/closure.stderr46
-rw-r--r--tests/ui/explicit-tail-calls/constck.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-arg-move.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs2
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs2
-rw-r--r--tests/ui/explicit-tail-calls/drop-order.rs2
-rw-r--r--tests/ui/explicit-tail-calls/in-closure.rs8
-rw-r--r--tests/ui/explicit-tail-calls/in-closure.stderr8
-rw-r--r--tests/ui/explicit-tail-calls/return-lifetime-sub.rs2
-rw-r--r--tests/ui/explicit-tail-calls/return-mismatches.rs2
-rw-r--r--tests/ui/explicit-tail-calls/signature-mismatch.rs33
-rw-r--r--tests/ui/explicit-tail-calls/signature-mismatch.stderr40
-rw-r--r--tests/ui/explicit-tail-calls/unsafeck.rs2
-rw-r--r--tests/ui/generic-associated-types/generic-associated-types-where.stderr2
-rw-r--r--tests/ui/generic-associated-types/impl_bounds.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-68643-broken-mir.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-74824.current.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-74824.next.stderr2
-rw-r--r--tests/ui/generic-associated-types/missing-bounds.stderr2
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr4
-rw-r--r--tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr21
-rw-r--r--tests/ui/impl-trait/auto-trait-selection.next.stderr21
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr10
-rw-r--r--tests/ui/impl-trait/issue-55872-1.stderr4
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr4
-rw-r--r--tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr4
-rw-r--r--tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs21
-rw-r--r--tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr4
-rw-r--r--tests/ui/issues/issue-6738.stderr2
-rw-r--r--tests/ui/kindck/kindck-impl-type-params.stderr8
-rw-r--r--tests/ui/layout/post-mono-layout-cycle-2.rs2
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr10
-rw-r--r--tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr2
-rw-r--r--tests/ui/methods/filter-relevant-fn-bounds.stderr8
-rw-r--r--tests/ui/mir/inline-wrong-abi.rs2
-rw-r--r--tests/ui/mir/validate/validate-unsize-cast.stderr2
-rw-r--r--tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr2
-rw-r--r--tests/ui/moves/issue-34721.stderr2
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.fixed6
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.rs6
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.stderr20
-rw-r--r--tests/ui/phantom-auto-trait.stderr4
-rw-r--r--tests/ui/polymorphization/abi_mismatch.rs20
-rw-r--r--tests/ui/polymorphization/abi_mismatch.stderr11
-rw-r--r--tests/ui/polymorphization/closure_in_upvar/fn.rs29
-rw-r--r--tests/ui/polymorphization/closure_in_upvar/fnmut.rs34
-rw-r--r--tests/ui/polymorphization/closure_in_upvar/fnonce.rs34
-rw-r--r--tests/ui/polymorphization/closure_in_upvar/other.rs38
-rw-r--r--tests/ui/polymorphization/const_parameters/closures.rs67
-rw-r--r--tests/ui/polymorphization/const_parameters/closures.stderr44
-rw-r--r--tests/ui/polymorphization/const_parameters/functions.rs37
-rw-r--r--tests/ui/polymorphization/const_parameters/functions.stderr17
-rw-r--r--tests/ui/polymorphization/coroutine.rs98
-rw-r--r--tests/ui/polymorphization/coroutine.stderr29
-rw-r--r--tests/ui/polymorphization/drop_shims/simple.rs22
-rw-r--r--tests/ui/polymorphization/drop_shims/transitive.rs27
-rw-r--r--tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs20
-rw-r--r--tests/ui/polymorphization/inline-incorrect-early-bound.rs27
-rw-r--r--tests/ui/polymorphization/inline-incorrect-early-bound.stderr15
-rw-r--r--tests/ui/polymorphization/inline-tainted-body.rs21
-rw-r--r--tests/ui/polymorphization/inline-tainted-body.stderr30
-rw-r--r--tests/ui/polymorphization/issue-74614.rs18
-rw-r--r--tests/ui/polymorphization/issue-74636.rs16
-rw-r--r--tests/ui/polymorphization/lifetimes.rs25
-rw-r--r--tests/ui/polymorphization/lifetimes.stderr17
-rw-r--r--tests/ui/polymorphization/normalized_sig_types.rs26
-rw-r--r--tests/ui/polymorphization/predicates.rs95
-rw-r--r--tests/ui/polymorphization/predicates.stderr45
-rw-r--r--tests/ui/polymorphization/promoted-function-1.rs12
-rw-r--r--tests/ui/polymorphization/promoted-function-1.stderr8
-rw-r--r--tests/ui/polymorphization/promoted-function-2.rs16
-rw-r--r--tests/ui/polymorphization/promoted-function-2.stderr17
-rw-r--r--tests/ui/polymorphization/promoted-function-3.rs14
-rw-r--r--tests/ui/polymorphization/promoted-function.rs15
-rw-r--r--tests/ui/polymorphization/symbol-ambiguity.rs22
-rw-r--r--tests/ui/polymorphization/too-many-generic-params.rs85
-rw-r--r--tests/ui/polymorphization/type_parameters/closures.rs161
-rw-r--r--tests/ui/polymorphization/type_parameters/closures.stderr80
-rw-r--r--tests/ui/polymorphization/type_parameters/functions.rs96
-rw-r--r--tests/ui/polymorphization/type_parameters/functions.stderr35
-rw-r--r--tests/ui/polymorphization/unsized_cast.rs30
-rw-r--r--tests/ui/polymorphization/unsized_cast.stderr38
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs2
-rw-r--r--tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr4
-rw-r--r--tests/ui/resolve/issue-55673.stderr2
-rw-r--r--tests/ui/sanitizer/cfi/coroutine.rs1
-rw-r--r--tests/ui/specialization/default-generic-associated-type-bound.stderr2
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr2
-rw-r--r--tests/ui/specialization/issue-33017.stderr2
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.stderr8
-rw-r--r--tests/ui/suggestions/assoc-const-as-fn.stderr2
-rw-r--r--tests/ui/suggestions/bound-suggestions.stderr12
-rw-r--r--tests/ui/suggestions/clone-bounds-121524.rs2
-rw-r--r--tests/ui/suggestions/clone-bounds-121524.stderr2
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr2
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.stderr2
-rw-r--r--tests/ui/suggestions/derive-macro-missing-bounds.stderr8
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr2
-rw-r--r--tests/ui/suggestions/issue-97677.stderr2
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr8
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr8
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr16
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr2
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr2
-rw-r--r--tests/ui/suggestions/restrict-type-argument.stderr12
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.stderr8
-rw-r--r--tests/ui/trait-bounds/unstable-trait-suggestion.rs19
-rw-r--r--tests/ui/trait-bounds/unstable-trait-suggestion.stderr34
-rw-r--r--tests/ui/traits/alias/wf.stderr2
-rw-r--r--tests/ui/traits/bad-method-typaram-kind.stderr2
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums.stderr6
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-chain.stderr4
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr8
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-fail.stderr4
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-pass.stderr4
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr4
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method.stderr4
-rw-r--r--tests/ui/traits/const-traits/const-closures.stderr12
-rw-r--r--tests/ui/traits/const-traits/trait-where-clause.stderr4
-rw-r--r--tests/ui/traits/copy-impl-cannot-normalize.stderr2
-rw-r--r--tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr2
-rw-r--r--tests/ui/traits/inductive-overflow/two-traits.stderr2
-rw-r--r--tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr4
-rw-r--r--tests/ui/traits/issue-21837.stderr2
-rw-r--r--tests/ui/traits/issue-43784-supertrait.stderr2
-rw-r--r--tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr2
-rw-r--r--tests/ui/traits/next-solver/dyn-incompatibility.stderr4
-rw-r--r--tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr2
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.stderr2
-rw-r--r--tests/ui/traits/next-solver/typeck/resolve-expectations.rs26
-rw-r--r--tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs8
-rw-r--r--tests/ui/tuple/builtin-fail.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/future.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-89686.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-90400-1.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-90400-2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/not_well_formed.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_generic.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/wf_check_closures.stderr2
-rw-r--r--tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr6
-rw-r--r--tests/ui/type/type-check-defaults.stderr2
-rw-r--r--tests/ui/type/type-check/missing_trait_impl.stderr8
-rw-r--r--tests/ui/typeck/bad-index-due-to-nested.stderr4
-rw-r--r--tests/ui/typeck/issue-90164.stderr2
-rw-r--r--tests/ui/typeck/typeck-default-trait-impl-send-param.stderr2
-rw-r--r--tests/ui/union/issue-81199.stderr2
-rw-r--r--tests/ui/unop/unop-move-semantics.stderr2
-rw-r--r--tests/ui/unsafe-fields/auto-traits.current.stderr17
-rw-r--r--tests/ui/unsafe-fields/auto-traits.next.stderr17
-rw-r--r--tests/ui/unsafe-fields/auto-traits.rs26
-rw-r--r--tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs (renamed from tests/ui/auxiliary/unsafe-fields-crate-dep.rs)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields-crate.rs (renamed from tests/ui/unsafe-fields-crate.rs)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields-crate.stderr (renamed from tests/ui/unsafe-fields-crate.stderr)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields-parse.rs (renamed from tests/ui/unsafe-fields-parse.rs)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields-parse.stderr (renamed from tests/ui/unsafe-fields-parse.stderr)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields.rs (renamed from tests/ui/unsafe-fields.rs)0
-rw-r--r--tests/ui/unsafe-fields/unsafe-fields.stderr (renamed from tests/ui/unsafe-fields.stderr)0
-rw-r--r--tests/ui/unsized/issue-115809.rs2
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs4
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr71
-rw-r--r--tests/ui/wf/issue-96810.stderr2
-rw-r--r--tests/ui/wf/wf-enum-bound.stderr2
-rw-r--r--tests/ui/wf/wf-enum-fields-struct-variant.stderr2
-rw-r--r--tests/ui/wf/wf-enum-fields.stderr2
-rw-r--r--tests/ui/wf/wf-fn-where-clause.stderr2
-rw-r--r--tests/ui/wf/wf-impl-associated-type-trait.stderr2
-rw-r--r--tests/ui/wf/wf-in-fn-arg.stderr2
-rw-r--r--tests/ui/wf/wf-in-fn-ret.stderr2
-rw-r--r--tests/ui/wf/wf-in-fn-type-arg.stderr2
-rw-r--r--tests/ui/wf/wf-in-fn-type-ret.stderr2
-rw-r--r--tests/ui/wf/wf-in-fn-where-clause.stderr2
-rw-r--r--tests/ui/wf/wf-in-obj-type-trait.stderr2
-rw-r--r--tests/ui/wf/wf-inherent-impl-method-where-clause.stderr2
-rw-r--r--tests/ui/wf/wf-inherent-impl-where-clause.stderr2
-rw-r--r--tests/ui/wf/wf-struct-bound.stderr2
-rw-r--r--tests/ui/wf/wf-struct-field.stderr2
-rw-r--r--tests/ui/wf/wf-trait-associated-type-bound.stderr2
-rw-r--r--tests/ui/wf/wf-trait-bound.stderr2
-rw-r--r--tests/ui/wf/wf-trait-superbound.stderr2
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr2
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr2
-rwxr-xr-xx.py9
494 files changed, 5367 insertions, 5245 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c11103af476..b42c99e1a6d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1450,6 +1450,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         ty::Param(param_ty) => Ok((
                             generics.type_param(param_ty, tcx),
                             predicate.trait_ref.print_trait_sugared().to_string(),
+                            Some(predicate.trait_ref.def_id),
                         )),
                         _ => Err(()),
                     }
@@ -1463,9 +1464,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 tcx,
                 hir_generics,
                 err,
-                predicates
-                    .iter()
-                    .map(|(param, constraint)| (param.name.as_str(), &**constraint, None)),
+                predicates.iter().map(|(param, constraint, def_id)| {
+                    (param.name.as_str(), &**constraint, *def_id)
+                }),
                 None,
             );
         }
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index e4f77472802..d81e7214961 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -46,24 +46,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5e7afe85cadb55c4c1176268a2ac046fdff8dfaeca39e18581b9dc319ca9e"
+checksum = "2ba4f80548f22dc9c43911907b5e322c5555544ee85f785115701e6a28c9abe1"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-bitset"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ab25ef3be935a80680e393183e1f94ef507e93a24a8369494d2c6818aedb3e3"
+checksum = "005884e3649c3e5ff2dc79e8a94b138f11569cc08a91244a292714d2a86e9156"
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900a19b84545924f1851cbfe386962edfc4ecbc3366a254825cf1ecbcda8ba08"
+checksum = "fe4036255ec33ce9a37495dfbcfc4e1118fd34e693eff9a1e106336b7cd16a9b"
 dependencies = [
  "bumpalo",
  "cranelift-bforest",
@@ -78,48 +78,49 @@ dependencies = [
  "log",
  "regalloc2",
  "rustc-hash",
+ "serde",
  "smallvec",
  "target-lexicon",
 ]
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c73b2395ffe9e7b4fdf7e2ebc052e7e27af13f68a964985346be4da477a5fc"
+checksum = "f7ca74f4b68319da11d39e894437cb6e20ec7c2e11fbbda823c3bf207beedff7"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d9ed0854e96a4ff0879bff39d078de8dea7f002721c9494c1fdb4e1baa86ccc"
+checksum = "897e54f433a0269c4187871aa06d452214d5515d228d5bdc22219585e9eef895"
 
 [[package]]
 name = "cranelift-control"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4aca921dd422e781409de0129c255768fec5dec1dae83239b497fb9138abb89"
+checksum = "29cb4018f5bf59fb53f515fa9d80e6f8c5ce19f198dc538984ebd23ecf8965ec"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d770e6605eccee15b49decdd82cd26f2b6404767802471459ea49c57379a98"
+checksum = "305399fd781a2953ac78c1396f02ff53144f39c33eb7fc7789cf4e8936d13a96"
 dependencies = [
  "cranelift-bitset",
 ]
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29268711cb889cb39215b10faf88b9087d4c9e1d2633581e4f722a2bf4bb4ef9"
+checksum = "9230b460a128d53653456137751d27baf567947a3ab8c0c4d6e31fd08036d81e"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -129,15 +130,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc65156f010aed1985767ad1bff0eb8d186743b7b03e23d0c17604a253e3f356"
+checksum = "b961e24ae3ec9813a24a15ae64bbd2a42e4de4d79a7f3225a412e3b94e78d1c8"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ba6b46367a4f466cfb1abe32793fa1a0f96d862251491b01a44726b8ed9445"
+checksum = "62699329d4ced20fe281fbaef45e11b473b7ab310491b4bdebcd8b818a8ef7fe"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -155,9 +156,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "007607022a4883ebdffc46c0925e2e10babf2a565ae78518034ade722aa825d2"
+checksum = "2f20b0b51ba962dac30fc7e812b86e4390d908acd4f59bcc8ac7610a8f3e0977"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -166,9 +167,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8bf9b361eaf5a7627647270fabf1dc910d993edbeaf272a652c107861ebe9c2"
+checksum = "4d5bd76df6c9151188dfa428c863b33da5b34561b67f43c0cf3f24a794f9fa1f"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -177,9 +178,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.113.0"
+version = "0.114.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ca5c38fa00c0cd943035391bdcc84ed00748f17c66c682e410f5a62f234d44"
+checksum = "ee231640a7ecceedd0f1f2782d9288db6a6908cc70675ed9427e3bf0ea6daacd"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -364,6 +365,26 @@ dependencies = [
 ]
 
 [[package]]
+name = "serde"
+version = "1.0.210"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.210"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "slice-group-by"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -412,9 +433,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "26.0.0"
+version = "27.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e458e6a1a010a53f86ac8d75837c0c6b2ce3e54b7503b2f1dc5629a4a541f5a"
+checksum = "91b218a92866f74f35162f5d03a4e0f62cd0e1cc624285b1014275e5d4575fad"
 dependencies = [
  "anyhow",
  "cfg-if",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index f352ef72cb0..b2fed3c490e 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.113.0", default-features = false, features = ["std", "unwind", "all-native-arch"] }
-cranelift-frontend = { version = "0.113.0" }
-cranelift-module = { version = "0.113.0" }
-cranelift-native = { version = "0.113.0" }
-cranelift-jit = { version = "0.113.0", optional = true }
-cranelift-object = { version = "0.113.0" }
+cranelift-codegen = { version = "0.114.0", default-features = false, features = ["std", "unwind", "all-native-arch"] }
+cranelift-frontend = { version = "0.114.0" }
+cranelift-module = { version = "0.114.0" }
+cranelift-native = { version = "0.114.0" }
+cranelift-jit = { version = "0.114.0", optional = true }
+cranelift-object = { version = "0.114.0" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.31", default-features = false, features = ["write"] }
 object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index 9292778806a..674acfbd309 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -1,4 +1,4 @@
-use crate::path::{Dirs, RelPath};
+use crate::path::Dirs;
 use crate::prepare::GitRepo;
 use crate::utils::{CargoProject, Compiler, spawn_and_wait};
 use crate::{CodegenBackend, SysrootKind, build_sysroot};
@@ -20,7 +20,7 @@ pub(crate) fn run(
     rustup_toolchain_name: Option<&str>,
     bootstrap_host_compiler: &Compiler,
 ) {
-    RelPath::DOWNLOAD.ensure_exists(dirs);
+    std::fs::create_dir_all(&dirs.download_dir).unwrap();
     ABI_CAFE_REPO.fetch(dirs);
     ABI_CAFE_REPO.patch(dirs);
 
diff --git a/compiler/rustc_codegen_cranelift/build_system/bench.rs b/compiler/rustc_codegen_cranelift/build_system/bench.rs
index ebeb6772250..73a0f325fc2 100644
--- a/compiler/rustc_codegen_cranelift/build_system/bench.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/bench.rs
@@ -3,7 +3,7 @@ use std::io::Write;
 use std::path::Path;
 use std::process::Command;
 
-use crate::path::{Dirs, RelPath};
+use crate::path::Dirs;
 use crate::prepare::GitRepo;
 use crate::rustc_info::get_file_name;
 use crate::utils::{Compiler, spawn_and_wait};
@@ -39,11 +39,11 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
     };
 
     eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
-    let cargo_clif = RelPath::DIST
-        .to_path(dirs)
+    let cargo_clif = dirs
+        .dist_dir
         .join(get_file_name(&bootstrap_host_compiler.rustc, "cargo_clif", "bin").replace('_', "-"));
     let manifest_path = SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).join("Cargo.toml");
-    let target_dir = RelPath::BUILD.join("simple_raytracer").to_path(dirs);
+    let target_dir = dirs.build_dir.join("simple_raytracer");
 
     let clean_cmd = format!(
         "RUSTC=rustc cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
@@ -68,7 +68,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
         target_dir = target_dir.display(),
     );
 
-    let bench_compile_markdown = RelPath::DIST.to_path(dirs).join("bench_compile.md");
+    let bench_compile_markdown = dirs.dist_dir.join("bench_compile.md");
 
     let bench_compile = hyperfine_command(
         1,
@@ -92,7 +92,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
 
     eprintln!("[BENCH RUN] ebobby/simple-raytracer");
 
-    let bench_run_markdown = RelPath::DIST.to_path(dirs).join("bench_run.md");
+    let bench_run_markdown = dirs.dist_dir.join("bench_run.md");
 
     let raytracer_cg_llvm = Path::new(".").join(get_file_name(
         &bootstrap_host_compiler.rustc,
@@ -120,7 +120,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
         ],
         &bench_run_markdown,
     );
-    bench_run.current_dir(RelPath::BUILD.to_path(dirs));
+    bench_run.current_dir(&dirs.build_dir);
     spawn_and_wait(bench_run);
 
     if let Some(gha_step_summary) = gha_step_summary.as_mut() {
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index 02da89f737c..72bc422523d 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -6,7 +6,7 @@ use crate::rustc_info::get_file_name;
 use crate::shared_utils::{rustflags_from_env, rustflags_to_cmd_env};
 use crate::utils::{CargoProject, Compiler, LogGroup};
 
-static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
+static CG_CLIF: CargoProject = CargoProject::new(&RelPath::source("."), "cg_clif");
 
 pub(crate) fn build_backend(
     dirs: &Dirs,
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index f1f4489bcbc..e47e9829916 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -22,9 +22,9 @@ pub(crate) fn build_sysroot(
 
     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
 
-    let dist_dir = RelPath::DIST.to_path(dirs);
+    let dist_dir = &dirs.dist_dir;
 
-    ensure_empty_dir(&dist_dir);
+    ensure_empty_dir(dist_dir);
     fs::create_dir_all(dist_dir.join("bin")).unwrap();
     fs::create_dir_all(dist_dir.join("lib")).unwrap();
 
@@ -55,7 +55,7 @@ pub(crate) fn build_sysroot(
         let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
         let wrapper_path = dist_dir.join(&wrapper_name);
         build_cargo_wrapper_cmd
-            .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
+            .arg(dirs.source_dir.join("scripts").join(&format!("{wrapper}.rs")))
             .arg("-o")
             .arg(&wrapper_path)
             .arg("-Cstrip=debuginfo");
@@ -85,7 +85,7 @@ pub(crate) fn build_sysroot(
         &cg_clif_dylib_path,
         sysroot_kind,
     );
-    host.install_into_sysroot(&dist_dir);
+    host.install_into_sysroot(dist_dir);
 
     if !is_native {
         build_sysroot_for_triple(
@@ -99,7 +99,7 @@ pub(crate) fn build_sysroot(
             &cg_clif_dylib_path,
             sysroot_kind,
         )
-        .install_into_sysroot(&dist_dir);
+        .install_into_sysroot(dist_dir);
     }
 
     let mut target_compiler = {
@@ -143,10 +143,10 @@ impl SysrootTarget {
     }
 }
 
-static STDLIB_SRC: RelPath = RelPath::BUILD.join("stdlib");
+static STDLIB_SRC: RelPath = RelPath::build("stdlib");
 static STANDARD_LIBRARY: CargoProject =
-    CargoProject::new(&STDLIB_SRC.join("library/sysroot"), "stdlib_target");
-static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup");
+    CargoProject::new(&RelPath::build("stdlib/library/sysroot"), "stdlib_target");
+static RTSTARTUP_SYSROOT: RelPath = RelPath::build("rtstartup");
 
 fn build_sysroot_for_triple(
     dirs: &Dirs,
@@ -247,6 +247,7 @@ fn build_clif_sysroot_for_triple(
     let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
     build_cmd.arg("--release");
     build_cmd.arg("--features").arg("backtrace panic-unwind compiler-builtins-no-f16-f128");
+    build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display()));
     build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     if compiler.triple.contains("apple") {
@@ -281,13 +282,14 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
         return None;
     }
 
-    RTSTARTUP_SYSROOT.ensure_fresh(dirs);
+    let rtstartup_sysroot = RTSTARTUP_SYSROOT.to_path(dirs);
+    ensure_empty_dir(&rtstartup_sysroot);
 
     let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup");
     let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
 
     for file in ["rsbegin", "rsend"] {
-        let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
+        let obj = rtstartup_sysroot.join(format!("{file}.o"));
         let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
         build_rtstartup_cmd
             .arg("--target")
diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs
index b68ac7c0926..99e6146657f 100644
--- a/compiler/rustc_codegen_cranelift/build_system/main.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/main.rs
@@ -185,12 +185,11 @@ fn main() {
         frozen,
     };
 
-    path::RelPath::BUILD.ensure_exists(&dirs);
+    std::fs::create_dir_all(&dirs.build_dir).unwrap();
 
     {
         // Make sure we always explicitly specify the target dir
-        let target =
-            path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
+        let target = dirs.build_dir.join("target_dir_should_be_set_explicitly");
         env::set_var("CARGO_TARGET_DIR", &target);
         let _ = std::fs::remove_file(&target);
         std::fs::File::create(target).unwrap();
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
index 35e7e81c528..20a81156b71 100644
--- a/compiler/rustc_codegen_cranelift/build_system/path.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/path.rs
@@ -1,8 +1,5 @@
-use std::fs;
 use std::path::PathBuf;
 
-use crate::utils::ensure_empty_dir;
-
 #[derive(Debug, Clone)]
 pub(crate) struct Dirs {
     pub(crate) source_dir: PathBuf,
@@ -16,54 +13,34 @@ pub(crate) struct Dirs {
 #[derive(Debug, Copy, Clone)]
 pub(crate) enum PathBase {
     Source,
-    Download,
     Build,
-    Dist,
 }
 
 impl PathBase {
     fn to_path(self, dirs: &Dirs) -> PathBuf {
         match self {
             PathBase::Source => dirs.source_dir.clone(),
-            PathBase::Download => dirs.download_dir.clone(),
             PathBase::Build => dirs.build_dir.clone(),
-            PathBase::Dist => dirs.dist_dir.clone(),
         }
     }
 }
 
 #[derive(Debug, Copy, Clone)]
-pub(crate) enum RelPath {
-    Base(PathBase),
-    Join(&'static RelPath, &'static str),
+pub(crate) struct RelPath {
+    base: PathBase,
+    suffix: &'static str,
 }
 
 impl RelPath {
-    pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
-    pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
-    pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
-    pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
-
-    pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
-    pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
-
-    pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
-        RelPath::Join(self, suffix)
+    pub(crate) const fn source(suffix: &'static str) -> RelPath {
+        RelPath { base: PathBase::Source, suffix }
     }
 
-    pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
-        match self {
-            RelPath::Base(base) => base.to_path(dirs),
-            RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
-        }
-    }
-
-    pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
-        fs::create_dir_all(self.to_path(dirs)).unwrap();
+    pub(crate) const fn build(suffix: &'static str) -> RelPath {
+        RelPath { base: PathBase::Build, suffix }
     }
 
-    pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
-        let path = self.to_path(dirs);
-        ensure_empty_dir(&path);
+    pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
+        self.base.to_path(dirs).join(self.suffix)
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index c6f979f0278..a4e9cb5f5c8 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -8,7 +8,7 @@ use crate::path::{Dirs, RelPath};
 use crate::utils::{copy_dir_recursively, ensure_empty_dir, spawn_and_wait};
 
 pub(crate) fn prepare(dirs: &Dirs) {
-    RelPath::DOWNLOAD.ensure_exists(dirs);
+    std::fs::create_dir_all(&dirs.download_dir).unwrap();
     crate::tests::RAND_REPO.fetch(dirs);
     crate::tests::REGEX_REPO.fetch(dirs);
 }
@@ -79,13 +79,13 @@ impl GitRepo {
 
     fn download_dir(&self, dirs: &Dirs) -> PathBuf {
         match self.url {
-            GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo).to_path(dirs),
+            GitRepoUrl::Github { user: _, repo } => dirs.download_dir.join(repo),
         }
     }
 
     pub(crate) const fn source_dir(&self) -> RelPath {
         match self.url {
-            GitRepoUrl::Github { user: _, repo } => RelPath::BUILD.join(repo),
+            GitRepoUrl::Github { user: _, repo } => RelPath::build(repo),
         }
     }
 
@@ -130,7 +130,7 @@ impl GitRepo {
         }
 
         let source_lockfile =
-            RelPath::PATCHES.to_path(dirs).join(format!("{}-lock.toml", self.patch_name));
+            dirs.source_dir.join("patches").join(format!("{}-lock.toml", self.patch_name));
         let target_lockfile = download_dir.join("Cargo.lock");
         if source_lockfile.exists() {
             assert!(!target_lockfile.exists());
@@ -191,7 +191,7 @@ fn init_git_repo(repo_dir: &Path) {
 }
 
 fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
-    let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
+    let mut patches: Vec<_> = fs::read_dir(dirs.source_dir.join("patches"))
         .unwrap()
         .map(|entry| entry.unwrap().path())
         .filter(|path| path.extension() == Some(OsStr::new("patch")))
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index fd94e80f631..08736db8ba0 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -7,10 +7,10 @@ use crate::path::{Dirs, RelPath};
 use crate::prepare::{GitRepo, apply_patches};
 use crate::rustc_info::get_default_sysroot;
 use crate::shared_utils::rustflags_from_env;
-use crate::utils::{CargoProject, Compiler, LogGroup, spawn_and_wait};
+use crate::utils::{CargoProject, Compiler, LogGroup, ensure_empty_dir, spawn_and_wait};
 use crate::{CodegenBackend, SysrootKind, build_sysroot, config};
 
-static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
+static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::build("example");
 
 struct TestCase {
     config: &'static str,
@@ -92,10 +92,6 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]),
     TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]),
     TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"),
-    TestCase::custom("aot.polymorphize_coroutine", &|runner| {
-        runner.run_rustc(&["example/polymorphize_coroutine.rs", "-Zpolymorphize"]);
-        runner.run_out_command("polymorphize_coroutine", &[]);
-    }),
     TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]),
     TestCase::custom("aot.gen_block_iterate", &|runner| {
         runner.run_rustc([
@@ -129,11 +125,11 @@ pub(crate) static REGEX_REPO: GitRepo = GitRepo::github(
 
 static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex_target");
 
-static PORTABLE_SIMD_SRC: RelPath = RelPath::BUILD.join("portable-simd");
+static PORTABLE_SIMD_SRC: RelPath = RelPath::build("portable-simd");
 
 static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target");
 
-static LIBCORE_TESTS_SRC: RelPath = RelPath::BUILD.join("coretests");
+static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests");
 
 static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target");
 
@@ -162,7 +158,7 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
             &LIBCORE_TESTS_SRC.to_path(&runner.dirs),
         );
 
-        let source_lockfile = RelPath::PATCHES.to_path(&runner.dirs).join("coretests-lock.toml");
+        let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml");
         let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock");
         fs::copy(source_lockfile, target_lockfile).unwrap();
 
@@ -267,7 +263,9 @@ pub(crate) fn run_tests(
             stdlib_source.clone(),
         );
 
-        BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
+        let path = BUILD_EXAMPLE_OUT_DIR.to_path(dirs);
+        ensure_empty_dir(&path);
+
         runner.run_testsuite(NO_SYSROOT_SUITE);
     } else {
         eprintln!("[SKIP] no_sysroot tests");
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index 22a9487a202..c2114caf869 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -93,7 +93,7 @@ impl CargoProject {
     }
 
     pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
-        RelPath::BUILD.join(self.target).to_path(dirs)
+        dirs.build_dir.join(self.target)
     }
 
     #[must_use]
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 527ec5303b6..b63597f60fc 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -42,7 +42,6 @@ aot.float-minmax-pass
 aot.mod_bench
 aot.issue-72793
 aot.issue-59326
-aot.polymorphize_coroutine
 aot.neon
 aot.gen_block_iterate
 aot.raw-dylib
diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
deleted file mode 100644
index 407da94c0f0..00000000000
--- a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
-
-use std::ops::Coroutine;
-use std::pin::Pin;
-
-fn main() {
-    run_coroutine::<i32>();
-}
-
-fn run_coroutine<T>() {
-    let mut coroutine = #[coroutine]
-    || {
-        yield;
-        return;
-    };
-    Pin::new(&mut coroutine).resume(());
-}
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 3078288c286..0b1d83c5630 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -8,6 +8,9 @@
     unboxed_closures
 )]
 #![allow(internal_features)]
+// FIXME once abi_unsupported_vector_types is a hard error disable the foo test when the respective
+// target feature is not enabled.
+#![allow(abi_unsupported_vector_types)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
index 1860810e7f3..161173d4765 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
@@ -38,7 +38,7 @@ index 42a26ae..5ac1042 100644
 @@ -1,3 +1,4 @@
 +#![cfg(test)]
  // tidy-alphabetical-start
- #![cfg_attr(bootstrap, feature(const_three_way_compare))]
- #![cfg_attr(bootstrap, feature(strict_provenance))]
+ #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
+ #![cfg_attr(test, feature(cfg_match))]
 --
 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
index 59653c6e875..06840624cef 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
@@ -14,10 +14,9 @@ diff --git a/lib.rs b/lib.rs
 index 1e336bf..35e6f54 100644
 --- a/lib.rs
 +++ b/lib.rs
-@@ -2,7 +2,6 @@
- #![cfg_attr(bootstrap, feature(const_three_way_compare))]
- #![cfg_attr(bootstrap, feature(strict_provenance))]
- #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
+@@ -2,6 +2,5 @@
+ #![cfg(test)]
+ // tidy-alphabetical-start
 -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
  #![cfg_attr(test, feature(cfg_match))]
  #![feature(alloc_layout_extra)]
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
index ada35145e29..6012af6a8dd 100644
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
@@ -4,22 +4,23 @@ Date: Fri, 9 Aug 2024 15:44:51 +0000
 Subject: [PATCH] Disable f16 and f128 in compiler-builtins
 
 ---
- library/sysroot/Cargo.toml | 2 +-
+ library/liballoc/Cargo.toml | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
+diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml
 index 7165c3e48af..968552ad435 100644
---- a/library/sysroot/Cargo.toml
-+++ b/library/sysroot/Cargo.toml
+--- a/library/alloc/Cargo.toml
++++ b/library/alloc/Cargo.toml
 @@ -11,7 +11,7 @@ test = { path = "../test" }
+ edition = "2021"
  
- # Forward features to the `std` crate as necessary
- [features]
--default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
-+default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind", "compiler-builtins-no-f16-f128"]
- backtrace = ["std/backtrace"]
- compiler-builtins-c = ["std/compiler-builtins-c"]
- compiler-builtins-mem = ["std/compiler-builtins-mem"]
+ [dependencies]
+ core = { path = "../core" }
+-compiler_builtins = { version = "=0.1.138", features = ['rustc-dep-of-std'] }
++compiler_builtins = { version = "=0.1.138", features = ['rustc-dep-of-std', 'no-f16-f128'] }
+ 
+ [dev-dependencies]
+ rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
 -- 
 2.34.1
 
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index a223cd7dbb8..8d935df4d1f 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-11-09"
+channel = "nightly-2024-12-06"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
 profile = "minimal"
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
index 92defd21cd9..a27b9983bf1 100644
--- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
@@ -33,6 +33,11 @@ fn main() {
         args.push(OsString::from("--sysroot"));
         args.push(OsString::from(sysroot.to_str().unwrap()));
     }
+    if passed_args.is_empty() {
+        // Don't pass any arguments when the user didn't pass any arguments
+        // either to ensure the help message is shown.
+        args.clear();
+    }
     args.extend(passed_args);
 
     let rustc = if let Some(rustc) = option_env!("RUSTC") {
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 5b3f2a91207..54f6baff4fe 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -35,13 +35,14 @@ full-bootstrap = true
 local-rebuild = true
 
 [rust]
+download-rustc = false
 codegen-backends = ["cranelift"]
 deny-warnings = false
 verbose-tests = false
 # The cg_clif sysroot doesn't contain llvm tools and unless llvm_tools is
 # disabled bootstrap will crash trying to copy llvm tools for the bootstrap
 # compiler.
-llvm_tools = false
+llvm-tools = false
 
 EOF
 popd
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh
index 770f2b6df6c..791d457993d 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh
@@ -11,22 +11,5 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
 cp ../Cargo.* compiler/rustc_codegen_cranelift/
 cp -r ../src compiler/rustc_codegen_cranelift/src
 
-# FIXME(rust-lang/rust#132719) remove once it doesn't break without this patch
-cat <<EOF | git apply -
-diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
-index 3394f2a84a0..cb980dd4d7c 100644
---- a/src/bootstrap/src/core/build_steps/compile.rs
-+++ b/src/bootstrap/src/core/build_steps/compile.rs
-@@ -1976,7 +1976,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
-             }
-         }
-
--        {
-+        if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
-             // \`llvm-strip\` is used by rustc, which is actually just a symlink to \`llvm-objcopy\`,
-             // so copy and rename \`llvm-objcopy\`.
-             let src_exe = exe("llvm-objcopy", target_compiler.host);
-EOF
-
 ./x.py build --stage 1 library/std
 popd
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index a820da286f5..e291ec20464 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -57,6 +57,7 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't
 rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
 rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes
 rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo
+rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported
 
 # requires LTO
 rm -r tests/run-make/cdylib
@@ -75,6 +76,8 @@ rm -r tests/ui/instrument-coverage/
 rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
 rm tests/ui/asm/aarch64/type-f16.rs
 rm tests/ui/float/conv-bits-runtime-const.rs
+rm tests/ui/consts/const-eval/float_methods.rs
+rm tests/ui/match/match-float.rs
 
 # optimization tests
 # ==================
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index cab5b35c18d..2466bfe60c7 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -125,8 +125,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         returns: Vec<AbiParam>,
         args: &[Value],
     ) -> Cow<'_, [Value]> {
-        if self.tcx.sess.target.is_like_windows {
-            let (mut params, mut args): (Vec<_>, Vec<_>) = params
+        // Pass i128 arguments by-ref on Windows.
+        let (params, args): (Vec<_>, Cow<'_, [_]>) = if self.tcx.sess.target.is_like_windows {
+            let (params, args): (Vec<_>, Vec<_>) = params
                 .into_iter()
                 .zip(args)
                 .map(|(param, &arg)| {
@@ -140,29 +141,42 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
                 })
                 .unzip();
 
-            let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128;
+            (params, args.into())
+        } else {
+            (params, args.into())
+        };
 
-            if indirect_ret_val {
-                params.insert(0, AbiParam::new(self.pointer_type));
-                let ret_ptr = self.create_stack_slot(16, 16);
-                args.insert(0, ret_ptr.get_addr(self));
-                self.lib_call_unadjusted(name, params, vec![], &args);
-                return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]);
+        // Return i128 using a return area pointer on Windows and s390x.
+        let adjust_ret_param =
+            if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" {
+                returns.len() == 1 && returns[0].value_type == types::I128
             } else {
-                return self.lib_call_unadjusted(name, params, returns, &args);
-            }
-        }
+                false
+            };
+
+        if adjust_ret_param {
+            let mut params = params;
+            let mut args = args.to_vec();
+
+            params.insert(0, AbiParam::new(self.pointer_type));
+            let ret_ptr = self.create_stack_slot(16, 16);
+            args.insert(0, ret_ptr.get_addr(self));
 
-        self.lib_call_unadjusted(name, params, returns, args)
+            self.lib_call_unadjusted(name, params, vec![], &args);
+
+            Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())])
+        } else {
+            Cow::Borrowed(self.lib_call_unadjusted(name, params, returns, &args))
+        }
     }
 
-    pub(crate) fn lib_call_unadjusted(
+    fn lib_call_unadjusted(
         &mut self,
         name: &str,
         params: Vec<AbiParam>,
         returns: Vec<AbiParam>,
         args: &[Value],
-    ) -> Cow<'_, [Value]> {
+    ) -> &[Value] {
         let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
         let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
         let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
@@ -175,7 +189,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         }
         let results = self.bcx.inst_results(call_inst);
         assert!(results.len() <= 2, "{}", results.len());
-        Cow::Borrowed(results)
+        results
     }
 }
 
@@ -380,8 +394,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
             def_id,
             fn_args,
             source_info.span,
-        )
-        .polymorphize(fx.tcx);
+        );
 
         if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
             if target.is_some() {
@@ -684,7 +697,7 @@ pub(crate) fn codegen_drop<'tcx>(
     target: BasicBlock,
 ) {
     let ty = drop_place.layout().ty;
-    let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx);
+    let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty);
 
     if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) =
         drop_instance.def
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 06cc5754894..34066eb83fc 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -6,6 +6,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_module::ModuleError;
 use rustc_ast::InlineAsmOptions;
 use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
+use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_index::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::InlineAsmMacro;
@@ -16,6 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 
 use crate::constant::ConstantCx;
 use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
+use crate::enable_verifier;
 use crate::inline_asm::codegen_naked_asm;
 use crate::prelude::*;
 use crate::pretty_clif::CommentWriter;
@@ -169,12 +171,13 @@ pub(crate) fn codegen_fn<'tcx>(
 
 pub(crate) fn compile_fn(
     cx: &mut crate::CodegenCx,
+    profiler: &SelfProfilerRef,
     cached_context: &mut Context,
     module: &mut dyn Module,
     codegened_func: CodegenedFunction,
 ) {
     let _timer =
-        cx.profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
+        profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
 
     let clif_comments = codegened_func.clif_comments;
 
@@ -212,7 +215,7 @@ pub(crate) fn compile_fn(
     };
 
     // Define function
-    cx.profiler.generic_activity("define function").run(|| {
+    profiler.generic_activity("define function").run(|| {
         context.want_disasm = cx.should_write_ir;
         match module.define_function(codegened_func.func_id, context) {
             Ok(()) => {}
@@ -253,7 +256,7 @@ pub(crate) fn compile_fn(
 
     // Define debuginfo for function
     let debug_context = &mut cx.debug_context;
-    cx.profiler.generic_activity("generate debug info").run(|| {
+    profiler.generic_activity("generate debug info").run(|| {
         if let Some(debug_context) = debug_context {
             codegened_func.func_debug_cx.unwrap().finalize(
                 debug_context,
@@ -264,11 +267,11 @@ pub(crate) fn compile_fn(
     });
 }
 
-pub(crate) fn verify_func(
-    tcx: TyCtxt<'_>,
-    writer: &crate::pretty_clif::CommentWriter,
-    func: &Function,
-) {
+fn verify_func(tcx: TyCtxt<'_>, writer: &crate::pretty_clif::CommentWriter, func: &Function) {
+    if !enable_verifier(tcx.sess) {
+        return;
+    }
+
     tcx.prof.generic_activity("verify clif ir").run(|| {
         let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder());
         match cranelift_codegen::verify_function(&func, &flags) {
@@ -670,8 +673,7 @@ fn codegen_stmt<'tcx>(
                                     def_id,
                                     args,
                                 )
-                                .unwrap()
-                                .polymorphize(fx.tcx),
+                                .unwrap(),
                             );
                             let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
                             lval.write_cvalue(fx, CValue::by_val(func_addr, to_layout));
@@ -757,8 +759,7 @@ fn codegen_stmt<'tcx>(
                                 def_id,
                                 args,
                                 ty::ClosureKind::FnOnce,
-                            )
-                            .polymorphize(fx.tcx);
+                            );
                             let func_ref = fx.get_function_ref(instance);
                             let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
                             lval.write_cvalue(fx, CValue::by_val(func_addr, lval.layout()));
@@ -1084,7 +1085,7 @@ fn codegen_panic_inner<'tcx>(
 
     let def_id = fx.tcx.require_lang_item(lang_item, span);
 
-    let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
+    let instance = Instance::mono(fx.tcx, def_id);
 
     if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
         fx.bcx.ins().trap(TrapCode::user(2).unwrap());
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index b6a4769e031..734574338d0 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -81,26 +81,6 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
     match bin_op {
         BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(),
         BinOp::Add | BinOp::Sub => None,
-        BinOp::Mul if is_signed => {
-            let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
-            let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
-            let lhs = lhs.load_scalar(fx);
-            let rhs = rhs.load_scalar(fx);
-            let oflow_ptr = oflow.to_ptr().get_addr(fx);
-            let res = fx.lib_call_unadjusted(
-                "__muloti4",
-                vec![
-                    AbiParam::new(types::I128),
-                    AbiParam::new(types::I128),
-                    AbiParam::new(fx.pointer_type),
-                ],
-                vec![AbiParam::new(types::I128)],
-                &[lhs, rhs, oflow_ptr],
-            )[0];
-            let oflow = oflow.to_cvalue(fx).load_scalar(fx);
-            let oflow = fx.bcx.ins().ireduce(types::I8, oflow);
-            Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty)))
-        }
         BinOp::Mul => {
             let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
             let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
@@ -110,7 +90,12 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
                 AbiParam::new(types::I128),
             ];
             let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
-            fx.lib_call("__rust_u128_mulo", param_types, vec![], &args);
+            fx.lib_call(
+                if is_signed { "__rust_i128_mulo" } else { "__rust_u128_mulo" },
+                param_types,
+                vec![],
+                &args,
+            );
             Some(out_place.to_cvalue(fx))
         }
         BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index 12bce680d9e..d784f6e9d9e 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -1,10 +1,3 @@
-use std::env;
-use std::str::FromStr;
-
-fn bool_env_var(key: &str) -> bool {
-    env::var(key).as_deref() == Ok("1")
-}
-
 /// The mode to use for compilation.
 #[derive(Copy, Clone, Debug)]
 pub enum CodegenMode {
@@ -16,19 +9,6 @@ pub enum CodegenMode {
     JitLazy,
 }
 
-impl FromStr for CodegenMode {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "aot" => Ok(CodegenMode::Aot),
-            "jit" => Ok(CodegenMode::Jit),
-            "jit-lazy" => Ok(CodegenMode::JitLazy),
-            _ => Err(format!("Unknown codegen mode `{}`", s)),
-        }
-    }
-}
-
 /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
 #[derive(Clone, Debug)]
 pub struct BackendConfig {
@@ -41,51 +21,22 @@ pub struct BackendConfig {
     ///
     /// Defaults to the value of `CG_CLIF_JIT_ARGS`.
     pub jit_args: Vec<String>,
-
-    /// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run
-    /// once before passing the clif ir to Cranelift for compilation.
-    ///
-    /// Defaults to true when the `CG_CLIF_ENABLE_VERIFIER` env var is set to 1 or when cg_clif is
-    /// compiled with debug assertions enabled or false otherwise. Can be set using
-    /// `-Cllvm-args=enable_verifier=...`.
-    pub enable_verifier: bool,
-
-    /// Don't cache object files in the incremental cache. Useful during development of cg_clif
-    /// to make it possible to use incremental mode for all analyses performed by rustc without
-    /// caching object files when their content should have been changed by a change to cg_clif.
-    ///
-    /// Defaults to true when the `CG_CLIF_DISABLE_INCR_CACHE` env var is set to 1 or false
-    /// otherwise. Can be set using `-Cllvm-args=disable_incr_cache=...`.
-    pub disable_incr_cache: bool,
-}
-
-impl Default for BackendConfig {
-    fn default() -> Self {
-        BackendConfig {
-            codegen_mode: CodegenMode::Aot,
-            jit_args: {
-                match std::env::var("CG_CLIF_JIT_ARGS") {
-                    Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
-                    Err(std::env::VarError::NotPresent) => vec![],
-                    Err(std::env::VarError::NotUnicode(s)) => {
-                        panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s);
-                    }
-                }
-            },
-            enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
-            disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
-        }
-    }
 }
 
 impl BackendConfig {
     /// Parse the configuration passed in using `-Cllvm-args`.
     pub fn from_opts(opts: &[String]) -> Result<Self, String> {
-        fn parse_bool(name: &str, value: &str) -> Result<bool, String> {
-            value.parse().map_err(|_| format!("failed to parse value `{}` for {}", value, name))
-        }
+        let mut config = BackendConfig {
+            codegen_mode: CodegenMode::Aot,
+            jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
+                Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
+                Err(std::env::VarError::NotPresent) => vec![],
+                Err(std::env::VarError::NotUnicode(s)) => {
+                    panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s);
+                }
+            },
+        };
 
-        let mut config = BackendConfig::default();
         for opt in opts {
             if opt.starts_with("-import-instr-limit") {
                 // Silently ignore -import-instr-limit. It is set by rust's build system even when
@@ -94,9 +45,14 @@ impl BackendConfig {
             }
             if let Some((name, value)) = opt.split_once('=') {
                 match name {
-                    "mode" => config.codegen_mode = value.parse()?,
-                    "enable_verifier" => config.enable_verifier = parse_bool(name, value)?,
-                    "disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?,
+                    "mode" => {
+                        config.codegen_mode = match value {
+                            "aot" => CodegenMode::Aot,
+                            "jit" => CodegenMode::Jit,
+                            "jit-lazy" => CodegenMode::JitLazy,
+                            _ => return Err(format!("Unknown codegen mode `{}`", value)),
+                        };
+                    }
                     _ => return Err(format!("Unknown option `{}`", name)),
                 }
             } else {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index abe6085b04f..3e7b81a96b6 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -452,8 +452,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
             let data_id = match reloc_target_alloc {
                 GlobalAlloc::Function { instance, .. } => {
                     assert_eq!(addend, 0);
-                    let func_id =
-                        crate::abi::import_function(tcx, module, instance.polymorphize(tcx));
+                    let func_id = crate::abi::import_function(tcx, module, instance);
                     let local_func_id = module.declare_func_in_data(func_id, &mut data);
                     data.write_function_addr(offset.bytes() as u32, local_func_id);
                     continue;
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 8eab73ad5f9..5bbcfc2cda7 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -1,6 +1,7 @@
 //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
 //! standalone executable.
 
+use std::env;
 use std::fs::{self, File};
 use std::io::BufWriter;
 use std::path::{Path, PathBuf};
@@ -25,13 +26,18 @@ use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
 use rustc_session::Session;
 use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
 
-use crate::BackendConfig;
+use crate::CodegenCx;
+use crate::base::CodegenedFunction;
 use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
 use crate::debuginfo::TypeDebugContext;
 use crate::global_asm::GlobalAsmConfig;
 use crate::prelude::*;
 use crate::unwind_module::UnwindModule;
 
+fn disable_incr_cache() -> bool {
+    env::var("CG_CLIF_DISABLE_INCR_CACHE").as_deref() == Ok("1")
+}
+
 struct ModuleCodegenResult {
     module_regular: CompiledModule,
     module_global_asm: Option<CompiledModule>,
@@ -63,10 +69,10 @@ impl OngoingCodegen {
         self,
         sess: &Session,
         outputs: &OutputFilenames,
-        backend_config: &BackendConfig,
     ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         let mut work_products = FxIndexMap::default();
         let mut modules = vec![];
+        let disable_incr_cache = disable_incr_cache();
 
         for module_codegen in self.modules {
             let module_codegen_result = match module_codegen {
@@ -87,7 +93,7 @@ impl OngoingCodegen {
             if let Some((work_product_id, work_product)) = existing_work_product {
                 work_products.insert(work_product_id, work_product);
             } else {
-                let work_product = if backend_config.disable_incr_cache {
+                let work_product = if disable_incr_cache {
                     None
                 } else if let Some(module_global_asm) = &module_global_asm {
                     rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
@@ -322,12 +328,8 @@ fn produce_final_output_artifacts(
     // These are used in linking steps and will be cleaned up afterward.
 }
 
-fn make_module(
-    sess: &Session,
-    backend_config: &BackendConfig,
-    name: String,
-) -> UnwindModule<ObjectModule> {
-    let isa = crate::build_isa(sess, backend_config);
+fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
+    let isa = crate::build_isa(sess);
 
     let mut builder =
         ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
@@ -412,7 +414,13 @@ fn emit_module(
         Err(err) => return Err(format!("error writing object file: {}", err)),
     };
 
-    prof.artifact_size("object_file", &*name, file.metadata().unwrap().len());
+    if prof.enabled() {
+        prof.artifact_size(
+            "object_file",
+            tmp_file.file_name().unwrap().to_string_lossy(),
+            file.metadata().unwrap().len(),
+        );
+    }
 
     Ok(CompiledModule {
         name,
@@ -486,91 +494,101 @@ fn reuse_workproduct_for_cgu(
     })
 }
 
+fn codegen_cgu_content(
+    tcx: TyCtxt<'_>,
+    module: &mut dyn Module,
+    cgu_name: rustc_span::Symbol,
+) -> (CodegenCx, Vec<CodegenedFunction>) {
+    let _timer = tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str());
+
+    let cgu = tcx.codegen_unit(cgu_name);
+    let mono_items = cgu.items_in_deterministic_order(tcx);
+
+    let mut cx = crate::CodegenCx::new(
+        tcx,
+        module.isa(),
+        tcx.sess.opts.debuginfo != DebugInfo::None,
+        cgu_name,
+    );
+    let mut type_dbg = TypeDebugContext::default();
+    super::predefine_mono_items(tcx, module, &mono_items);
+    let mut codegened_functions = vec![];
+    for (mono_item, _) in mono_items {
+        match mono_item {
+            MonoItem::Fn(inst) => {
+                if let Some(codegened_function) = crate::base::codegen_fn(
+                    tcx,
+                    &mut cx,
+                    &mut type_dbg,
+                    Function::new(),
+                    module,
+                    inst,
+                ) {
+                    codegened_functions.push(codegened_function);
+                }
+            }
+            MonoItem::Static(def_id) => {
+                let data_id = crate::constant::codegen_static(tcx, module, def_id);
+                if let Some(debug_context) = &mut cx.debug_context {
+                    debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
+                }
+            }
+            MonoItem::GlobalAsm(item_id) => {
+                crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id);
+            }
+        }
+    }
+    crate::main_shim::maybe_create_entry_wrapper(tcx, module, false, cgu.is_primary());
+
+    (cx, codegened_functions)
+}
+
 fn module_codegen(
     tcx: TyCtxt<'_>,
-    (backend_config, global_asm_config, cgu_name, token): (
-        BackendConfig,
+    (global_asm_config, cgu_name, token): (
         Arc<GlobalAsmConfig>,
         rustc_span::Symbol,
         ConcurrencyLimiterToken,
     ),
 ) -> OngoingModuleCodegen {
-    let (cgu_name, mut cx, mut module, codegened_functions) =
-        tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str()).run(|| {
-            let cgu = tcx.codegen_unit(cgu_name);
-            let mono_items = cgu.items_in_deterministic_order(tcx);
-
-            let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string());
-
-            let mut cx = crate::CodegenCx::new(
-                tcx,
-                module.isa(),
-                tcx.sess.opts.debuginfo != DebugInfo::None,
-                cgu_name,
-            );
-            let mut type_dbg = TypeDebugContext::default();
-            super::predefine_mono_items(tcx, &mut module, &mono_items);
-            let mut codegened_functions = vec![];
-            for (mono_item, _) in mono_items {
-                match mono_item {
-                    MonoItem::Fn(inst) => {
-                        if let Some(codegened_function) = crate::base::codegen_fn(
-                            tcx,
-                            &mut cx,
-                            &mut type_dbg,
-                            Function::new(),
-                            &mut module,
-                            inst,
-                        ) {
-                            codegened_functions.push(codegened_function);
-                        }
-                    }
-                    MonoItem::Static(def_id) => {
-                        let data_id = crate::constant::codegen_static(tcx, &mut module, def_id);
-                        if let Some(debug_context) = &mut cx.debug_context {
-                            debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
-                        }
-                    }
-                    MonoItem::GlobalAsm(item_id) => {
-                        crate::global_asm::codegen_global_asm_item(
-                            tcx,
-                            &mut cx.global_asm,
-                            item_id,
-                        );
-                    }
-                }
-            }
-            crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, false, cgu.is_primary());
+    let mut module = make_module(tcx.sess, cgu_name.as_str().to_string());
 
-            let cgu_name = cgu.name().as_str().to_owned();
+    let (mut cx, codegened_functions) = codegen_cgu_content(tcx, &mut module, cgu_name);
 
-            (cgu_name, cx, module, codegened_functions)
-        });
+    let cgu_name = cgu_name.as_str().to_owned();
 
     let producer = crate::debuginfo::producer(tcx.sess);
 
+    let profiler = tcx.prof.clone();
+
     OngoingModuleCodegen::Async(std::thread::spawn(move || {
-        cx.profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| {
+        profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| {
             cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler(
-                cx.profiler.clone(),
+                profiler.clone(),
             )));
 
             let mut cached_context = Context::new();
             for codegened_func in codegened_functions {
-                crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func);
+                crate::base::compile_fn(
+                    &mut cx,
+                    &profiler,
+                    &mut cached_context,
+                    &mut module,
+                    codegened_func,
+                );
             }
         });
 
         let global_asm_object_file =
-            cx.profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| {
+            profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| {
                 crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
             })?;
 
         let codegen_result =
-            cx.profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
+            profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
                 emit_cgu(
                     &global_asm_config.output_filenames,
-                    &cx.profiler,
+                    &profiler,
                     cgu_name,
                     module,
                     cx.debug_context,
@@ -583,9 +601,63 @@ fn module_codegen(
     }))
 }
 
+fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> CompiledModule {
+    use rustc_middle::mir::mono::CodegenUnitNameBuilder;
+
+    let _timer = tcx.sess.timer("write compressed metadata");
+
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+    let metadata_cgu_name = cgu_name_builder
+        .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata"))
+        .as_str()
+        .to_string();
+
+    let tmp_file =
+        tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
+
+    let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
+    let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
+
+    if let Err(err) = std::fs::write(&tmp_file, obj) {
+        tcx.dcx().fatal(format!("error writing metadata object file: {}", err));
+    }
+
+    CompiledModule {
+        name: metadata_cgu_name,
+        kind: ModuleKind::Metadata,
+        object: Some(tmp_file),
+        dwarf_object: None,
+        bytecode: None,
+        assembly: None,
+        llvm_ir: None,
+    }
+}
+
+fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
+    let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string());
+    let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
+
+    if created_alloc_shim {
+        let product = allocator_module.finish();
+
+        match emit_module(
+            tcx.output_filenames(()),
+            &tcx.sess.prof,
+            product.object,
+            ModuleKind::Allocator,
+            "allocator_shim".to_owned(),
+            &crate::debuginfo::producer(tcx.sess),
+        ) {
+            Ok(allocator_module) => Some(allocator_module),
+            Err(err) => tcx.dcx().fatal(err),
+        }
+    } else {
+        None
+    }
+}
+
 pub(crate) fn run_aot(
     tcx: TyCtxt<'_>,
-    backend_config: BackendConfig,
     metadata: EncodedMetadata,
     need_metadata_module: bool,
 ) -> Box<OngoingCodegen> {
@@ -631,9 +703,10 @@ pub(crate) fn run_aot(
 
     let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx));
 
+    let disable_incr_cache = disable_incr_cache();
     let (todo_cgus, done_cgus) =
         cgus.into_iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
-            _ if backend_config.disable_incr_cache => true,
+            _ if disable_incr_cache => true,
             CguReuse::No => true,
             CguReuse::PreLto | CguReuse::PostLto => false,
         });
@@ -647,12 +720,7 @@ pub(crate) fn run_aot(
                 .with_task(
                     dep_node,
                     tcx,
-                    (
-                        backend_config.clone(),
-                        global_asm_config.clone(),
-                        cgu.name(),
-                        concurrency_limiter.acquire(tcx.dcx()),
-                    ),
+                    (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())),
                     module_codegen,
                     Some(rustc_middle::dep_graph::hash_result),
                 )
@@ -666,62 +734,10 @@ pub(crate) fn run_aot(
         modules
     });
 
-    let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
-    let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
-
-    let allocator_module = if created_alloc_shim {
-        let product = allocator_module.finish();
+    let allocator_module = emit_allocator_module(tcx);
 
-        match emit_module(
-            tcx.output_filenames(()),
-            &tcx.sess.prof,
-            product.object,
-            ModuleKind::Allocator,
-            "allocator_shim".to_owned(),
-            &crate::debuginfo::producer(tcx.sess),
-        ) {
-            Ok(allocator_module) => Some(allocator_module),
-            Err(err) => tcx.dcx().fatal(err),
-        }
-    } else {
-        None
-    };
-
-    let metadata_module = if need_metadata_module {
-        let (metadata_cgu_name, tmp_file) = tcx.sess.time("write compressed metadata", || {
-            use rustc_middle::mir::mono::CodegenUnitNameBuilder;
-
-            let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
-            let metadata_cgu_name = cgu_name_builder
-                .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata"))
-                .as_str()
-                .to_string();
-
-            let tmp_file =
-                tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
-
-            let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
-            let obj = create_compressed_metadata_file(tcx.sess, &metadata, &symbol_name);
-
-            if let Err(err) = std::fs::write(&tmp_file, obj) {
-                tcx.dcx().fatal(format!("error writing metadata object file: {}", err));
-            }
-
-            (metadata_cgu_name, tmp_file)
-        });
-
-        Some(CompiledModule {
-            name: metadata_cgu_name,
-            kind: ModuleKind::Metadata,
-            object: Some(tmp_file),
-            dwarf_object: None,
-            bytecode: None,
-            assembly: None,
-            llvm_ir: None,
-        })
-    } else {
-        None
-    };
+    let metadata_module =
+        if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None };
 
     Box::new(OngoingCodegen {
         modules,
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index ae9578eeffb..d68948966ea 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -11,12 +11,12 @@ use cranelift_jit::{JITBuilder, JITModule};
 use rustc_codegen_ssa::CrateInfo;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_session::Session;
-use rustc_span::Symbol;
+use rustc_span::sym;
 
 use crate::debuginfo::TypeDebugContext;
 use crate::prelude::*;
 use crate::unwind_module::UnwindModule;
-use crate::{BackendConfig, CodegenCx, CodegenMode};
+use crate::{CodegenCx, CodegenMode};
 
 struct JitState {
     jit_module: UnwindModule<JITModule>,
@@ -59,14 +59,10 @@ impl UnsafeMessage {
     }
 }
 
-fn create_jit_module(
-    tcx: TyCtxt<'_>,
-    backend_config: &BackendConfig,
-    hotswap: bool,
-) -> (UnwindModule<JITModule>, CodegenCx) {
+fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) {
     let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
 
-    let isa = crate::build_isa(tcx.sess, backend_config);
+    let isa = crate::build_isa(tcx.sess);
     let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
     jit_builder.hotswap(hotswap);
     crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
@@ -81,7 +77,7 @@ fn create_jit_module(
     (jit_module, cx)
 }
 
-pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
+pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<String>) -> ! {
     if !tcx.sess.opts.output_types.should_codegen() {
         tcx.dcx().fatal("JIT mode doesn't work with `cargo check`");
     }
@@ -90,11 +86,8 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         tcx.dcx().fatal("can't jit non-executable crate");
     }
 
-    let (mut jit_module, mut cx) = create_jit_module(
-        tcx,
-        &backend_config,
-        matches!(backend_config.codegen_mode, CodegenMode::JitLazy),
-    );
+    let (mut jit_module, mut cx) =
+        create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy));
     let mut cached_context = Context::new();
 
     let (_, cgus) = tcx.collect_and_partition_mono_items(());
@@ -110,7 +103,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         super::predefine_mono_items(tcx, &mut jit_module, &mono_items);
         for (mono_item, _) in mono_items {
             match mono_item {
-                MonoItem::Fn(inst) => match backend_config.codegen_mode {
+                MonoItem::Fn(inst) => match codegen_mode {
                     CodegenMode::Aot => unreachable!(),
                     CodegenMode::Jit => {
                         codegen_and_compile_fn(
@@ -151,7 +144,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
     );
 
     let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())
-        .chain(backend_config.jit_args.iter().map(|arg| &**arg))
+        .chain(jit_args.iter().map(|arg| &**arg))
         .map(|arg| CString::new(arg).unwrap())
         .collect::<Vec<_>>();
 
@@ -211,7 +204,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
     instance: Instance<'tcx>,
 ) {
     cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler(
-        cx.profiler.clone(),
+        tcx.prof.clone(),
     )));
 
     tcx.prof.generic_activity("codegen and compile fn").run(|| {
@@ -227,7 +220,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
             module,
             instance,
         ) {
-            crate::base::compile_fn(cx, cached_context, module, codegened_func);
+            crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func);
         }
     });
 }
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index d74c366a87f..33726056cc1 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -102,13 +102,12 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
                     // Pass a wrapper rather than the function itself as the function itself may not
                     // be exported from the main codegen unit and may thus be unreachable from the
                     // object file created by an external assembler.
-                    let inline_asm_index = fx.cx.inline_asm_index.get();
-                    fx.cx.inline_asm_index.set(inline_asm_index + 1);
                     let wrapper_name = format!(
                         "__inline_asm_{}_wrapper_n{}",
                         fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
-                        inline_asm_index
+                        fx.cx.inline_asm_index
                     );
+                    fx.cx.inline_asm_index += 1;
                     let sig =
                         get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
                     create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
@@ -167,13 +166,12 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
     asm_gen.allocate_registers();
     asm_gen.allocate_stack_slots();
 
-    let inline_asm_index = fx.cx.inline_asm_index.get();
-    fx.cx.inline_asm_index.set(inline_asm_index + 1);
     let asm_name = format!(
         "__inline_asm_{}_n{}",
         fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
-        inline_asm_index
+        fx.cx.inline_asm_index
     );
+    fx.cx.inline_asm_index += 1;
 
     let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
     fx.cx.global_asm.push_str(&generated_asm);
@@ -266,13 +264,12 @@ pub(crate) fn codegen_naked_asm<'tcx>(
                     // Pass a wrapper rather than the function itself as the function itself may not
                     // be exported from the main codegen unit and may thus be unreachable from the
                     // object file created by an external assembler.
-                    let inline_asm_index = cx.inline_asm_index.get();
-                    cx.inline_asm_index.set(inline_asm_index + 1);
                     let wrapper_name = format!(
                         "__inline_asm_{}_wrapper_n{}",
                         cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
-                        inline_asm_index
+                        cx.inline_asm_index
                     );
+                    cx.inline_asm_index += 1;
                     let sig =
                         get_function_sig(tcx, module.target_config().default_call_conv, instance);
                     create_wrapper_function(module, sig, &wrapper_name, symbol.name);
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 3318c0797ec..5f1b71eff6b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1270,8 +1270,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
         }
 
         sym::cold_path => {
-            // This is a no-op. The intrinsic is just a hint to the optimizer.
-            // We still have an impl here to avoid it being turned into a call.
+            fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
         }
 
         // Unimplemented intrinsics must have a fallback body. The fallback body is obtained
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index cac9975f04c..c9486a730e1 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -34,7 +34,7 @@ extern crate rustc_target;
 extern crate rustc_driver;
 
 use std::any::Any;
-use std::cell::{Cell, RefCell};
+use std::env;
 use std::sync::Arc;
 
 use cranelift_codegen::isa::TargetIsa;
@@ -42,7 +42,6 @@ use cranelift_codegen::settings::{self, Configurable};
 use rustc_codegen_ssa::CodegenResults;
 use rustc_codegen_ssa::back::versioned_llvm_target;
 use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_session::Session;
@@ -123,11 +122,10 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
 /// The codegen context holds any information shared between the codegen of individual functions
 /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
 struct CodegenCx {
-    profiler: SelfProfilerRef,
     output_filenames: Arc<OutputFilenames>,
     should_write_ir: bool,
     global_asm: String,
-    inline_asm_index: Cell<usize>,
+    inline_asm_index: usize,
     debug_context: Option<DebugContext>,
     cgu_name: Symbol,
 }
@@ -142,11 +140,10 @@ impl CodegenCx {
             None
         };
         CodegenCx {
-            profiler: tcx.prof.clone(),
             output_filenames: tcx.output_filenames(()).clone(),
             should_write_ir: crate::pretty_clif::should_write_ir(tcx),
             global_asm: String::new(),
-            inline_asm_index: Cell::new(0),
+            inline_asm_index: 0,
             debug_context,
             cgu_name,
         }
@@ -154,7 +151,7 @@ impl CodegenCx {
 }
 
 pub struct CraneliftCodegenBackend {
-    pub config: RefCell<Option<BackendConfig>>,
+    pub config: Option<BackendConfig>,
 }
 
 impl CodegenBackend for CraneliftCodegenBackend {
@@ -176,13 +173,6 @@ impl CodegenBackend for CraneliftCodegenBackend {
             sess.dcx()
                 .fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
         }
-
-        let mut config = self.config.borrow_mut();
-        if config.is_none() {
-            let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args)
-                .unwrap_or_else(|err| sess.dcx().fatal(err));
-            *config = Some(new_config);
-        }
     }
 
     fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
@@ -215,12 +205,15 @@ impl CodegenBackend for CraneliftCodegenBackend {
         need_metadata_module: bool,
     ) -> Box<dyn Any> {
         tcx.dcx().abort_if_errors();
-        let config = self.config.borrow().clone().unwrap();
+        let config = self.config.clone().unwrap_or_else(|| {
+            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
+                .unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
+        });
         match config.codegen_mode {
-            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
+            CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module),
             CodegenMode::Jit | CodegenMode::JitLazy => {
                 #[cfg(feature = "jit")]
-                driver::jit::run_jit(tcx, config);
+                driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args);
 
                 #[cfg(not(feature = "jit"))]
                 tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
@@ -236,14 +229,20 @@ impl CodegenBackend for CraneliftCodegenBackend {
     ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         let _timer = sess.timer("finish_ongoing_codegen");
 
-        ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(
-            sess,
-            outputs,
-            self.config.borrow().as_ref().unwrap(),
-        )
+        ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(sess, outputs)
     }
 }
 
+/// Determine if the Cranelift ir verifier should run.
+///
+/// Returns true when `-Zverify-llvm-ir` is passed, the `CG_CLIF_ENABLE_VERIFIER` env var is set to
+/// 1 or when cg_clif is compiled with debug assertions enabled or false otherwise.
+fn enable_verifier(sess: &Session) -> bool {
+    sess.verify_llvm_ir()
+        || cfg!(debug_assertions)
+        || env::var("CG_CLIF_ENABLE_VERIFIER").as_deref() == Ok("1")
+}
+
 fn target_triple(sess: &Session) -> target_lexicon::Triple {
     // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS.
     // See <https://github.com/bytecodealliance/target-lexicon/pull/113>
@@ -253,14 +252,14 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple {
     }
 }
 
-fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIsa + 'static> {
+fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
     use target_lexicon::BinaryFormat;
 
     let target_triple = crate::target_triple(sess);
 
     let mut flags_builder = settings::builder();
     flags_builder.enable("is_pic").unwrap();
-    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
+    let enable_verifier = if enable_verifier(sess) { "true" } else { "false" };
     flags_builder.set("enable_verifier", enable_verifier).unwrap();
     flags_builder.set("regalloc_checker", enable_verifier).unwrap();
 
@@ -295,6 +294,16 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs
         }
     }
 
+    if let target_lexicon::OperatingSystem::Windows = target_triple.operating_system {
+        // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510
+        flags_builder.enable("enable_multi_ret_implicit_sret").unwrap();
+    }
+
+    if let target_lexicon::Architecture::S390x = target_triple.architecture {
+        // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510
+        flags_builder.enable("enable_multi_ret_implicit_sret").unwrap();
+    }
+
     if let target_lexicon::Architecture::Aarch64(_)
     | target_lexicon::Architecture::Riscv64(_)
     | target_lexicon::Architecture::X86_64 = target_triple.architecture
@@ -347,5 +356,5 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs
 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    Box::new(CraneliftCodegenBackend { config: RefCell::new(None) })
+    Box::new(CraneliftCodegenBackend { config: None })
 }
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 2ee4ff5cec7..e480f21b9df 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -24,7 +24,7 @@ pub(crate) fn maybe_create_entry_wrapper(
     };
 
     if main_def_id.is_local() {
-        let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
+        let instance = Instance::mono(tcx, main_def_id);
         if module.get_name(tcx.symbol_name(instance).name).is_none() {
             return;
         }
@@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
             }
         };
 
-        let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
+        let instance = Instance::mono(tcx, rust_main_def_id);
 
         let main_name = tcx.symbol_name(instance).name;
         let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
@@ -117,8 +117,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                     report.def_id,
                     tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
                     DUMMY_SP,
-                )
-                .polymorphize(tcx);
+                );
 
                 let report_name = tcx.symbol_name(report).name;
                 let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
@@ -143,8 +142,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                     start_def_id,
                     tcx.mk_args(&[main_ret_ty.into()]),
                     DUMMY_SP,
-                )
-                .polymorphize(tcx);
+                );
                 let start_func_id = import_function(tcx, m, start_instance);
 
                 let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 6676e684ca0..c17d1f30fbe 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -1005,9 +1005,6 @@ pub(crate) fn assert_assignable<'tcx>(
                 }
             }
         }
-        (ty::Param(_), _) | (_, ty::Param(_)) if fx.tcx.sess.opts.unstable_opts.polymorphize => {
-            // No way to check if it is correct or not with polymorphization enabled
-        }
         _ => {
             assert_eq!(
                 from_ty,
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 3846d025537..f67dcf0cb11 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -544,7 +544,10 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
 
 impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
-        X86Abi { regparm: self.tcx.sess.opts.unstable_opts.regparm }
+        X86Abi {
+            regparm: self.tcx.sess.opts.unstable_opts.regparm,
+            reg_struct_return: self.tcx.sess.opts.unstable_opts.reg_struct_return,
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 56b51275a53..457072b1a5b 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -6,7 +6,6 @@ tests/ui/functions-closures/parallel-codegen-closures.rs
 tests/ui/linkage-attr/linkage1.rs
 tests/ui/lto/dylib-works.rs
 tests/ui/numbers-arithmetic/saturating-float-casts.rs
-tests/ui/polymorphization/promoted-function.rs
 tests/ui/sepcomp/sepcomp-cci.rs
 tests/ui/sepcomp/sepcomp-extern.rs
 tests/ui/sepcomp/sepcomp-fns-backwards.rs
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 8852dec7d9f..adfe8aeb5c5 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -302,10 +302,9 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                             (value, AddressSpace::DATA)
                         }
                     }
-                    GlobalAlloc::Function { instance, .. } => (
-                        self.get_fn_addr(instance.polymorphize(self.tcx)),
-                        self.data_layout().instruction_address_space,
-                    ),
+                    GlobalAlloc::Function { instance, .. } => {
+                        (self.get_fn_addr(instance), self.data_layout().instruction_address_space)
+                    }
                     GlobalAlloc::VTable(ty, dyn_ty) => {
                         let alloc = self
                             .tcx
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index dee67baaee9..59275254022 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -471,8 +471,6 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
             AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
         },
         ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
-        // Type parameters from polymorphized functions.
-        ty::Param(_) => build_param_type_di_node(cx, t),
         _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
     };
 
@@ -871,26 +869,6 @@ fn build_foreign_type_di_node<'ll, 'tcx>(
     )
 }
 
-fn build_param_type_di_node<'ll, 'tcx>(
-    cx: &CodegenCx<'ll, 'tcx>,
-    t: Ty<'tcx>,
-) -> DINodeCreationResult<'ll> {
-    debug!("build_param_type_di_node: {:?}", t);
-    let name = format!("{t:?}");
-    DINodeCreationResult {
-        di_node: unsafe {
-            llvm::LLVMRustDIBuilderCreateBasicType(
-                DIB(cx),
-                name.as_c_char_ptr(),
-                name.len(),
-                Size::ZERO.bits(),
-                DW_ATE_unsigned,
-            )
-        },
-        already_stored_in_typemap: false,
-    }
-}
-
 pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
     tcx: TyCtxt<'tcx>,
     codegen_unit_name: &str,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 6c4f6d37972..cf72c2ed742 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -432,11 +432,8 @@ fn push_debuginfo_type_name<'tcx>(
                 push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited);
             }
         }
-        // Type parameters from polymorphized functions.
-        ty::Param(_) => {
-            write!(output, "{t:?}").unwrap();
-        }
-        ty::Error(_)
+        ty::Param(_)
+        | ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
         | ty::Alias(..)
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index e3ed12b5ce6..b0a1dedd646 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -847,10 +847,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
             ty::FnDef(def_id, args) => (
-                Some(
-                    ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span)
-                        .polymorphize(bx.tcx()),
-                ),
+                Some(ty::Instance::expect_resolve(
+                    bx.tcx(),
+                    bx.typing_env(),
+                    def_id,
+                    args,
+                    fn_span,
+                )),
                 None,
             ),
             ty::FnPtr(..) => (None, Some(callee.immediate())),
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f63b2d139c5..cf537392234 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -478,8 +478,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     def_id,
                                     args,
                                 )
-                                .unwrap()
-                                .polymorphize(bx.cx().tcx());
+                                .unwrap();
                                 OperandValue::Immediate(bx.get_fn_addr(instance))
                             }
                             _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
@@ -493,8 +492,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     def_id,
                                     args,
                                     ty::ClosureKind::FnOnce,
-                                )
-                                .polymorphize(bx.cx().tcx());
+                                );
                                 OperandValue::Immediate(bx.cx().get_fn_addr(instance))
                             }
                             _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 489bb54a6f9..23f2aa4d029 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -140,7 +140,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                             err,
                             param_ty.name.as_str(),
                             &constraint,
-                            None,
+                            Some(trait_ref.def_id),
                             None,
                         );
                     }
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index e49d702127d..817acfcca74 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -168,9 +168,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
         })
     }
 
-    fn expose_ptr(
-        _ecx: &mut InterpCx<'tcx, Self>,
-        _ptr: interpret::Pointer<Self::Provenance>,
+    fn expose_provenance(
+        _ecx: &InterpCx<'tcx, Self>,
+        _provenance: Self::Provenance,
     ) -> interpret::InterpResult<'tcx> {
         unimplemented!()
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index b27e3606f38..11e0fac51d8 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -21,9 +21,8 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy,
-    InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine,
-    interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup,
-    throw_unsup_format,
+    InterpCx, InterpResult, MPlaceTy, OpTy, RangeSet, Scalar, compile_time_machine, interp_ok,
+    throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format,
 };
 
 /// When hitting this many interpreted terminators we emit a deny by default lint
@@ -586,7 +585,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
     }
 
     #[inline(always)]
-    fn expose_ptr(_ecx: &mut InterpCx<'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
+    fn expose_provenance(
+        _ecx: &InterpCx<'tcx, Self>,
+        _provenance: Self::Provenance,
+    ) -> InterpResult<'tcx> {
         // This is only reachable with -Zunleash-the-miri-inside-of-you.
         throw_unsup_format!("exposing pointers is not possible at compile-time")
     }
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index c95e51f0a1f..ef3e96784ce 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -238,7 +238,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let scalar = src.to_scalar();
         let ptr = scalar.to_pointer(self)?;
         match ptr.into_pointer_or_addr() {
-            Ok(ptr) => M::expose_ptr(self, ptr)?,
+            Ok(ptr) => M::expose_provenance(self, ptr.provenance)?,
             Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP.
         };
         interp_ok(ImmTy::from_scalar(
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index dbe09d55b2d..a180d5da941 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -327,11 +327,11 @@ pub trait Machine<'tcx>: Sized {
         addr: u64,
     ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>;
 
-    /// Marks a pointer as exposed, allowing it's provenance
+    /// Marks a pointer as exposed, allowing its provenance
     /// to be recovered. "Pointer-to-int cast"
-    fn expose_ptr(
-        ecx: &mut InterpCx<'tcx, Self>,
-        ptr: Pointer<Self::Provenance>,
+    fn expose_provenance(
+        ecx: &InterpCx<'tcx, Self>,
+        provenance: Self::Provenance,
     ) -> InterpResult<'tcx>;
 
     /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 277d293597a..027ba9644cb 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -944,6 +944,52 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         interp_ok(())
     }
 
+    /// Handle the effect an FFI call might have on the state of allocations.
+    /// This overapproximates the modifications which external code might make to memory:
+    /// We set all reachable allocations as initialized, mark all provenances as exposed
+    /// and overwrite them with `Provenance::WILDCARD`.
+    pub fn prepare_for_native_call(
+        &mut self,
+        id: AllocId,
+        initial_prov: M::Provenance,
+    ) -> InterpResult<'tcx> {
+        // Expose provenance of the root allocation.
+        M::expose_provenance(self, initial_prov)?;
+
+        let mut done = FxHashSet::default();
+        let mut todo = vec![id];
+        while let Some(id) = todo.pop() {
+            if !done.insert(id) {
+                // We already saw this allocation before, don't process it again.
+                continue;
+            }
+            let info = self.get_alloc_info(id);
+
+            // If there is no data behind this pointer, skip this.
+            if !matches!(info.kind, AllocKind::LiveData) {
+                continue;
+            }
+
+            // Expose all provenances in this allocation, and add them to `todo`.
+            let alloc = self.get_alloc_raw(id)?;
+            for prov in alloc.provenance().provenances() {
+                M::expose_provenance(self, prov)?;
+                if let Some(id) = prov.get_alloc_id() {
+                    todo.push(id);
+                }
+            }
+
+            // Prepare for possible write from native code if mutable.
+            if info.mutbl.is_mut() {
+                self.get_alloc_raw_mut(id)?
+                    .0
+                    .prepare_for_native_write()
+                    .map_err(|e| e.to_interp_error(id))?;
+            }
+        }
+        interp_ok(())
+    }
+
     /// Create a lazy debug printer that prints the given allocation and all allocations it points
     /// to, recursively.
     #[must_use]
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 8bb5f173a56..ecb7c3fc93c 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -14,10 +14,8 @@ use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationR
 
 /// Checks whether a type contains generic parameters which must be instantiated.
 ///
-/// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization
-/// types may be "concrete enough" even though they still contain generic parameters in
-/// case these parameters are unused.
-pub(crate) fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
+/// In case it does, returns a `TooGeneric` const eval error.
+pub(crate) fn ensure_monomorphic_enough<'tcx, T>(_tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
 where
     T: TypeVisitable<TyCtxt<'tcx>>,
 {
@@ -27,11 +25,9 @@ where
     }
 
     struct FoundParam;
-    struct UsedParamsNeedInstantiationVisitor<'tcx> {
-        tcx: TyCtxt<'tcx>,
-    }
+    struct UsedParamsNeedInstantiationVisitor {}
 
-    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor {
         type Result = ControlFlow<FoundParam>;
 
         fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
@@ -41,25 +37,7 @@ where
 
             match *ty.kind() {
                 ty::Param(_) => ControlFlow::Break(FoundParam),
-                ty::Closure(def_id, args)
-                | ty::CoroutineClosure(def_id, args, ..)
-                | ty::Coroutine(def_id, args, ..)
-                | ty::FnDef(def_id, args) => {
-                    let instance = ty::InstanceKind::Item(def_id);
-                    let unused_params = self.tcx.unused_generic_params(instance);
-                    for (index, arg) in args.into_iter().enumerate() {
-                        let index = index
-                            .try_into()
-                            .expect("more generic parameters than can fit into a `u32`");
-                        // Only recurse when generic parameters in fns, closures and coroutines
-                        // are used and have to be instantiated.
-                        //
-                        // Just in case there are closures or coroutines within this arg,
-                        // recurse.
-                        if unused_params.is_used(index) && arg.has_param() {
-                            return arg.visit_with(self);
-                        }
-                    }
+                ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::FnDef(..) => {
                     ControlFlow::Continue(())
                 }
                 _ => ty.super_visit_with(self),
@@ -74,7 +52,7 @@ where
         }
     }
 
-    let mut vis = UsedParamsNeedInstantiationVisitor { tcx };
+    let mut vis = UsedParamsNeedInstantiationVisitor {};
     if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) {
         throw_inval!(TooGeneric);
     } else {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index fd08b35d242..3bf485c2eb6 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1104,10 +1104,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         WarnFollowing, EncodeCrossCrate::No
     ),
     rustc_attr!(
-        TEST, rustc_polymorphize_error, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes
-    ),
-    rustc_attr!(
         TEST, rustc_def_path, Normal, template!(Word),
         WarnFollowing, EncodeCrossCrate::No
     ),
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index ff449a858d6..2e227ead14a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -279,7 +279,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     } else {
                         let mut err = self.dcx().create_err(err);
                         if suggest_constraining_type_param(
-                            tcx, generics, &mut err, &qself_str, &trait_ref, None, None,
+                            tcx,
+                            generics,
+                            &mut err,
+                            &qself_str,
+                            &trait_ref,
+                            Some(best_trait),
+                            None,
                         ) && !identically_named
                         {
                             // We suggested constraining a type parameter, but the associated item on it
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index cb4209116ac..3313339abb3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -29,10 +29,9 @@ use rustc_errors::codes::*;
 use rustc_errors::{
     Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
 };
-use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{GenericArg, GenericArgs, HirId};
+use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
@@ -999,6 +998,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                         self.lower_const_arg(ct, FeedConstTy::No).into()
                                     }
                                 };
+                                if term.references_error() {
+                                    continue;
+                                }
                                 // FIXME(#97583): This isn't syntactically well-formed!
                                 where_bounds.push(format!(
                                     "        T: {trait}::{assoc_name} = {term}",
@@ -2089,7 +2091,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 qpath.span(),
                 format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
             ),
-            hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id),
+            hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon),
             hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
         }
     }
@@ -2180,27 +2182,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
     /// becomes `Unevaluated`.
     #[instrument(skip(self), level = "debug")]
-    fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> {
+    fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> {
         let tcx = self.tcx();
 
-        let body_id = match tcx.hir_node_by_def_id(def) {
-            hir::Node::AnonConst(ac) => ac.body,
-            node => span_bug!(
-                tcx.def_span(def.to_def_id()),
-                "from_anon_const can only process anonymous constants, not {node:?}"
-            ),
-        };
-
-        let expr = &tcx.hir().body(body_id).value;
+        let expr = &tcx.hir().body(anon.body).value;
         debug!(?expr);
 
-        let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
+        let ty = tcx
+            .type_of(anon.def_id)
+            .no_bound_vars()
+            .expect("const parameter types cannot be generic");
 
         match self.try_lower_anon_const_lit(ty, expr) {
             Some(v) => v,
             None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
-                def: def.to_def_id(),
-                args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()),
+                def: anon.def_id.to_def_id(),
+                args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()),
             }),
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index bfdf764d299..243313ee876 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -57,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // type in that case)
         let mut all_arms_diverge = Diverges::WarnedAlways;
 
-        let expected = orig_expected.adjust_for_branches(self);
+        let expected =
+            orig_expected.try_structurally_resolve_and_adjust_for_branches(self, expr.span);
         debug!(?expected);
 
         let mut coercion = {
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 4653458b5dd..6d95b6917e2 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -39,10 +39,14 @@ impl<'a, 'tcx> Expectation<'tcx> {
     // an expected type. Otherwise, we might write parts of the type
     // when checking the 'then' block which are incompatible with the
     // 'else' branch.
-    pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
+    pub(super) fn try_structurally_resolve_and_adjust_for_branches(
+        &self,
+        fcx: &FnCtxt<'a, 'tcx>,
+        span: Span,
+    ) -> Expectation<'tcx> {
         match *self {
             ExpectHasType(ety) => {
-                let ety = fcx.shallow_resolve(ety);
+                let ety = fcx.try_structurally_resolve_type(span, ety);
                 if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
             }
             ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 4699b342cec..04c06169d33 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
         let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
-            match ty.kind() {
+            match self.try_structurally_resolve_type(expr.span, ty).kind() {
                 ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
                     if oprnd.is_syntactic_place_expr() {
                         // Places may legitimately have unsized types.
@@ -1293,7 +1293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let cond_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
 
-        let expected = orig_expected.adjust_for_branches(self);
+        let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self, sp);
         let then_ty = self.check_expr_with_expectation(then_expr, expected);
         let then_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
@@ -1354,8 +1354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rhs: &'tcx hir::Expr<'tcx>,
         span: Span,
     ) -> Ty<'tcx> {
-        let expected_ty = expected.coercion_target_type(self, expr.span);
-        if expected_ty == self.tcx.types.bool {
+        let expected_ty = expected.only_has_type(self);
+        if expected_ty == Some(self.tcx.types.bool) {
             let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span);
             return Ty::new_error(self.tcx, guar);
         }
@@ -1639,7 +1639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_ty = if !args.is_empty() {
             let coerce_to = expected
                 .to_option(self)
-                .and_then(|uty| match *uty.kind() {
+                .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() {
                     ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                     _ => None,
                 })
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 30c838b74af..44582390a4b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -936,18 +936,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // can be collated pretty easily if needed.
 
         // Next special case: if there is only one "Incompatible" error, just emit that
-        if let [
+        if let &[
             Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
         ] = &errors[..]
         {
-            let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
-            let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
+            let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
+            let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
             let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
-            let mut err =
-                self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *err);
+            let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
             self.emit_coerce_suggestions(
                 &mut err,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 provided_ty,
                 Expectation::rvalue_hint(self, expected_ty)
                     .only_has_type(self)
@@ -982,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.suggest_ptr_null_mut(
                 expected_ty,
                 provided_ty,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 &mut err,
             );
 
@@ -992,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 call_ident,
                 expected_ty,
                 provided_ty,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 is_method,
             );
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index d42915f4110..f53c7b5cc2d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -876,7 +876,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
                 || tcx.hir().body_const_context(def_id).is_some()
             {
                 tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
-                tcx.ensure().unused_generic_params(ty::InstanceKind::Item(def_id.to_def_id()));
             }
         }
     });
@@ -895,8 +894,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
     // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
     // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
     // in MIR optimizations that may only be reachable through codegen, or other codepaths
-    // that requires the optimized/ctfe MIR, such as polymorphization, coroutine bodies,
-    // or evaluating consts.
+    // that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
     if tcx.sess.opts.unstable_opts.validate_mir {
         sess.time("ensuring_final_MIR_is_computable", || {
             tcx.hir().par_body_owners(|def_id| {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 3c4d9c2e928..e76e9ca9f85 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -832,6 +832,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(precise_enum_drop_elaboration, false);
     tracked!(profile_sample_use, Some(PathBuf::from("abc")));
     tracked!(profiler_runtime, "abc".to_string());
+    tracked!(reg_struct_return, true);
     tracked!(regparm, Some(3));
     tracked!(relax_elf_relocations, Some(true));
     tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index a89096beb8c..f01ad31d0bb 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -269,7 +269,6 @@ provide! { tcx, def_id, other, cdata,
     lookup_default_body_stability => { table }
     lookup_deprecation_entry => { table }
     params_in_repr => { table }
-    unused_generic_params => { table_direct }
     def_kind => { cdata.def_kind(def_id.index) }
     impl_parent => { table }
     defaultness => { table_direct }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a34ea18f716..d4ea1276d00 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1767,10 +1767,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             {
                 record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
             }
-
-            let instance = ty::InstanceKind::Item(def_id.to_def_id());
-            let unused = tcx.unused_generic_params(instance);
-            self.tables.unused_generic_params.set(def_id.local_def_index, unused);
         }
 
         // Encode all the deduced parameter attributes for everything that has MIR, even for items
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a486ad42482..a5e21ab51fd 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -395,7 +395,6 @@ define_tables! {
     inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
     associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
     opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
-    unused_generic_params: Table<DefIndex, UnusedGenericParams>,
     // Reexported names are not associated with individual `DefId`s,
     // e.g. a glob import can introduce a lot of names, all with the same `DefId`.
     // That's why the encoded list needs to contain `ModChild` structures describing all the names
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 509f2667b35..d6f8fed755f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -643,6 +643,28 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         Ok(())
     }
 
+    /// Initialize all previously uninitialized bytes in the entire allocation, and set
+    /// provenance of everything to `Wildcard`. Before calling this, make sure all
+    /// provenance in this allocation is exposed!
+    pub fn prepare_for_native_write(&mut self) -> AllocResult {
+        let full_range = AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) };
+        // Overwrite uninitialized bytes with 0, to ensure we don't leak whatever their value happens to be.
+        for chunk in self.init_mask.range_as_init_chunks(full_range) {
+            if !chunk.is_init() {
+                let uninit_bytes = &mut self.bytes
+                    [chunk.range().start.bytes_usize()..chunk.range().end.bytes_usize()];
+                uninit_bytes.fill(0);
+            }
+        }
+        // Mark everything as initialized now.
+        self.mark_init(full_range, true);
+
+        // Set provenance of all bytes to wildcard.
+        self.provenance.write_wildcards(self.len());
+
+        Ok(())
+    }
+
     /// Remove all provenance in the given memory range.
     pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
         self.provenance.clear(range, cx)?;
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 5c47fc6a399..3a83b184d83 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -195,6 +195,25 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
 
         Ok(())
     }
+
+    /// Overwrites all provenance in the allocation with wildcard provenance.
+    ///
+    /// Provided for usage in Miri and panics otherwise.
+    pub fn write_wildcards(&mut self, alloc_size: usize) {
+        assert!(
+            Prov::OFFSET_IS_ADDR,
+            "writing wildcard provenance is not supported when `OFFSET_IS_ADDR` is false"
+        );
+        let wildcard = Prov::WILDCARD.unwrap();
+
+        // Remove all pointer provenances, then write wildcards into the whole byte range.
+        self.ptrs.clear();
+        let last = Size::from_bytes(alloc_size);
+        let bytes = self.bytes.get_or_insert_with(Box::default);
+        for offset in Size::ZERO..last {
+            bytes.insert(offset, wildcard);
+        }
+    }
 }
 
 /// A partial, owned list of provenance to transfer into another allocation.
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 1d5afe22573..25c7c26ddd9 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -66,6 +66,9 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
     ///   pointer, and implement ptr-to-int transmutation by stripping provenance.
     const OFFSET_IS_ADDR: bool;
 
+    /// If wildcard provenance is implemented, contains the unique, general wildcard provenance variant.
+    const WILDCARD: Option<Self>;
+
     /// Determines how a pointer should be printed.
     fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result;
 
@@ -168,6 +171,9 @@ impl Provenance for CtfeProvenance {
     // so ptr-to-int casts are not possible (since we do not know the global physical offset).
     const OFFSET_IS_ADDR: bool = false;
 
+    // `CtfeProvenance` does not implement wildcard provenance.
+    const WILDCARD: Option<Self> = None;
+
     fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Print AllocId.
         fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag
@@ -197,6 +203,9 @@ impl Provenance for AllocId {
     // so ptr-to-int casts are not possible (since we do not know the global physical offset).
     const OFFSET_IS_ADDR: bool = false;
 
+    // `AllocId` does not implement wildcard provenance.
+    const WILDCARD: Option<Self> = None;
+
     fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Forward `alternate` flag to `alloc_id` printing.
         if f.alternate() {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index df110fdc20a..d04876d0bef 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -82,7 +82,7 @@ use crate::ty::print::{PrintTraitRefExt, describe_as_module};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::{
     self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
-    TyCtxtFeed, UnusedGenericParams,
+    TyCtxtFeed,
 };
 use crate::{dep_graph, mir, thir};
 
@@ -916,6 +916,12 @@ rustc_queries! {
         cache_on_disk_if { true }
     }
 
+    /// Checks well-formedness of tail calls (`become f()`).
+    query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> {
+        desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) }
+        cache_on_disk_if { true }
+    }
+
     /// Returns the types assumed to be well formed while "inside" of the given item.
     ///
     /// Note that we've liberated the late bound regions of function signatures, so
@@ -2042,15 +2048,6 @@ rustc_queries! {
         desc { "getting codegen unit `{sym}`" }
     }
 
-    query unused_generic_params(key: ty::InstanceKind<'tcx>) -> UnusedGenericParams {
-        cache_on_disk_if { key.def_id().is_local() }
-        desc {
-            |tcx| "determining which generic parameters are unused by `{}`",
-                tcx.def_path_str(key.def_id())
-        }
-        separate_provide_extern
-    }
-
     query backend_optimization_level(_: ()) -> OptLevel {
         desc { "optimization level used by backend" }
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 3cbb2a3acf5..d4835bb07f6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -585,6 +585,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.trait_def(trait_def_id).implement_via_object
     }
 
+    fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
+        self.trait_def(trait_def_id).safety == hir::Safety::Unsafe
+    }
+
     fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
         self.is_impl_trait_in_trait(def_id)
     }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index fd807882e0f..604f1da26c6 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,11 +1,12 @@
 //! Diagnostics related methods for `Ty`.
 
-use std::borrow::Cow;
 use std::fmt::Write;
 use std::ops::ControlFlow;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display};
+use rustc_errors::{
+    Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize,
+};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind};
@@ -161,7 +162,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
     true
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
 enum SuggestChangingConstraintsMessage<'a> {
     RestrictBoundFurther,
     RestrictType { ty: &'a str },
@@ -172,7 +173,7 @@ enum SuggestChangingConstraintsMessage<'a> {
 
 fn suggest_changing_unsized_bound(
     generics: &hir::Generics<'_>,
-    suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
+    suggestions: &mut Vec<(Span, String, String, SuggestChangingConstraintsMessage<'_>)>,
     param: &hir::GenericParam<'_>,
     def_id: Option<DefId>,
 ) {
@@ -207,7 +208,8 @@ fn suggest_changing_unsized_bound(
             continue;
         }
 
-        let mut push_suggestion = |sp, msg| suggestions.push((sp, String::new(), msg));
+        let mut push_suggestion =
+            |sp, msg| suggestions.push((sp, "Sized".to_string(), String::new(), msg));
 
         if predicate.bounds.len() == unsized_bounds.len() {
             // All the bounds are unsized bounds, e.g.
@@ -278,8 +280,25 @@ pub fn suggest_constraining_type_params<'a>(
     span_to_replace: Option<Span>,
 ) -> bool {
     let mut grouped = FxHashMap::default();
+    let mut unstable_suggestion = false;
     param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
-        grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id))
+        let stable = match def_id {
+            Some(def_id) => match tcx.lookup_stability(def_id) {
+                Some(s) => s.level.is_stable(),
+                None => true,
+            },
+            None => true,
+        };
+        if stable || tcx.sess.is_nightly_build() {
+            grouped.entry(param_name).or_insert(Vec::new()).push((
+                constraint,
+                def_id,
+                if stable { "" } else { "unstable " },
+            ));
+            if !stable {
+                unstable_suggestion = true;
+            }
+        }
     });
 
     let mut applicability = Applicability::MachineApplicable;
@@ -290,16 +309,21 @@ pub fn suggest_constraining_type_params<'a>(
         let Some(param) = param else { return false };
 
         {
-            let mut sized_constraints = constraints.extract_if(|(_, def_id)| {
+            let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| {
                 def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
             });
-            if let Some((_, def_id)) = sized_constraints.next() {
+            if let Some((_, def_id, _)) = sized_constraints.next() {
                 applicability = Applicability::MaybeIncorrect;
 
                 err.span_label(param.span, "this type parameter needs to be `Sized`");
                 suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id);
             }
         }
+        let bound_message = if constraints.iter().any(|(_, def_id, _)| def_id.is_none()) {
+            SuggestChangingConstraintsMessage::RestrictBoundFurther
+        } else {
+            SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name }
+        };
 
         // in the scenario like impl has stricter requirements than trait,
         // we should not suggest restrict bound on the impl, here we double check
@@ -312,15 +336,54 @@ pub fn suggest_constraining_type_params<'a>(
             .collect();
 
         constraints
-            .retain(|(_, def_id)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def)));
+            .retain(|(_, def_id, _)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def)));
 
         if constraints.is_empty() {
             continue;
         }
 
-        let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
+        let mut constraint = constraints.iter().map(|&(c, _, _)| c).collect::<Vec<_>>();
         constraint.sort();
         constraint.dedup();
+        let all_known = constraints.iter().all(|&(_, def_id, _)| def_id.is_some());
+        let all_stable = constraints.iter().all(|&(_, _, stable)| stable.is_empty());
+        let all_unstable = constraints.iter().all(|&(_, _, stable)| !stable.is_empty());
+        let post = if all_stable || all_unstable {
+            // Don't redundantly say "trait `X`, trait `Y`", instead "traits `X` and `Y`"
+            let mut trait_names = constraints
+                .iter()
+                .map(|&(c, def_id, _)| match def_id {
+                    None => format!("`{c}`"),
+                    Some(def_id) => format!("`{}`", tcx.item_name(def_id)),
+                })
+                .collect::<Vec<_>>();
+            trait_names.sort();
+            trait_names.dedup();
+            let n = trait_names.len();
+            let stable = if all_stable { "" } else { "unstable " };
+            let trait_ = if all_known { format!("trait{}", pluralize!(n)) } else { String::new() };
+            format!("{stable}{trait_}{}", match &trait_names[..] {
+                [t] => format!(" {t}"),
+                [ts @ .., last] => format!(" {} and {last}", ts.join(", ")),
+                [] => return false,
+            },)
+        } else {
+            // We're more explicit when there's a mix of stable and unstable traits.
+            let mut trait_names = constraints
+                .iter()
+                .map(|&(c, def_id, stable)| match def_id {
+                    None => format!("`{c}`"),
+                    Some(def_id) => format!("{stable}trait `{}`", tcx.item_name(def_id)),
+                })
+                .collect::<Vec<_>>();
+            trait_names.sort();
+            trait_names.dedup();
+            match &trait_names[..] {
+                [t] => t.to_string(),
+                [ts @ .., last] => format!("{} and {last}", ts.join(", ")),
+                [] => return false,
+            }
+        };
         let constraint = constraint.join(" + ");
         let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| {
             let suggestion = if span_to_replace.is_some() {
@@ -333,13 +396,11 @@ pub fn suggest_constraining_type_params<'a>(
                 format!(" {constraint}")
             };
 
-            use SuggestChangingConstraintsMessage::RestrictBoundFurther;
-
             if let Some(open_paren_sp) = open_paren_sp {
-                suggestions.push((open_paren_sp, "(".to_string(), RestrictBoundFurther));
-                suggestions.push((span, format!("){suggestion}"), RestrictBoundFurther));
+                suggestions.push((open_paren_sp, post.clone(), "(".to_string(), bound_message));
+                suggestions.push((span, post.clone(), format!("){suggestion}"), bound_message));
             } else {
-                suggestions.push((span, suggestion, RestrictBoundFurther));
+                suggestions.push((span, post.clone(), suggestion, bound_message));
             }
         };
 
@@ -397,7 +458,8 @@ pub fn suggest_constraining_type_params<'a>(
             //                                           - insert: `, X: Bar`
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
-                constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
+                post,
+                constraints.iter().fold(String::new(), |mut string, &(constraint, _, _)| {
                     write!(string, ", {param_name}: {constraint}").unwrap();
                     string
                 }),
@@ -426,6 +488,7 @@ pub fn suggest_constraining_type_params<'a>(
             // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
+                post,
                 format!("{where_prefix} {param_name}: {constraint}"),
                 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
             ));
@@ -439,6 +502,7 @@ pub fn suggest_constraining_type_params<'a>(
         if let Some(colon_span) = param.colon_span {
             suggestions.push((
                 colon_span.shrink_to_hi(),
+                post,
                 format!(" {constraint}"),
                 SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
             ));
@@ -451,6 +515,7 @@ pub fn suggest_constraining_type_params<'a>(
         //          - help: consider restricting this type parameter with `T: Foo`
         suggestions.push((
             param.span.shrink_to_hi(),
+            post,
             format!(": {constraint}"),
             SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
         ));
@@ -459,39 +524,46 @@ pub fn suggest_constraining_type_params<'a>(
     // FIXME: remove the suggestions that are from derive, as the span is not correct
     suggestions = suggestions
         .into_iter()
-        .filter(|(span, _, _)| !span.in_derive_expansion())
+        .filter(|(span, _, _, _)| !span.in_derive_expansion())
         .collect::<Vec<_>>();
-
+    let suggested = !suggestions.is_empty();
     if suggestions.len() == 1 {
-        let (span, suggestion, msg) = suggestions.pop().unwrap();
+        let (span, post, suggestion, msg) = suggestions.pop().unwrap();
         let msg = match msg {
             SuggestChangingConstraintsMessage::RestrictBoundFurther => {
-                Cow::from("consider further restricting this bound")
+                format!("consider further restricting this bound")
+            }
+            SuggestChangingConstraintsMessage::RestrictTypeFurther { ty }
+            | SuggestChangingConstraintsMessage::RestrictType { ty }
+                if ty.starts_with("impl ") =>
+            {
+                format!("consider restricting opaque type `{ty}` with {post}")
             }
             SuggestChangingConstraintsMessage::RestrictType { ty } => {
-                Cow::from(format!("consider restricting type parameter `{ty}`"))
+                format!("consider restricting type parameter `{ty}` with {post}")
             }
             SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
-                Cow::from(format!("consider further restricting type parameter `{ty}`"))
+                format!("consider further restricting type parameter `{ty}` with {post}")
             }
             SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
-                Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
+                format!("consider removing the `?Sized` bound to make the type parameter `Sized`")
             }
             SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
-                Cow::from("consider replacing `?Sized` with `Sized`")
+                format!("consider replacing `?Sized` with `Sized`")
             }
         };
 
         err.span_suggestion_verbose(span, msg, suggestion, applicability);
     } else if suggestions.len() > 1 {
+        let post = if unstable_suggestion { " (some of them are unstable traits)" } else { "" };
         err.multipart_suggestion_verbose(
-            "consider restricting type parameters",
-            suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
+            format!("consider restricting type parameters{post}"),
+            suggestions.into_iter().map(|(span, _, suggestion, _)| (span, suggestion)).collect(),
             applicability,
         );
     }
 
-    true
+    suggested
 }
 
 /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 3d4ce112a64..65c909e70f6 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -19,8 +19,8 @@ use crate::error;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name};
 use crate::ty::{
-    self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
-    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+    TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 
 /// An `InstanceKind` along with the args that are needed to substitute the instance.
@@ -917,116 +917,6 @@ impl<'tcx> Instance<'tcx> {
             tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
         }
     }
-
-    /// Returns a new `Instance` where generic parameters in `instance.args` are replaced by
-    /// identity parameters if they are determined to be unused in `instance.def`.
-    pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
-        debug!("polymorphize: running polymorphization analysis");
-        if !tcx.sess.opts.unstable_opts.polymorphize {
-            return self;
-        }
-
-        let polymorphized_args = polymorphize(tcx, self.def, self.args);
-        debug!("polymorphize: self={:?} polymorphized_args={:?}", self, polymorphized_args);
-        Self { def: self.def, args: polymorphized_args }
-    }
-}
-
-fn polymorphize<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    instance: ty::InstanceKind<'tcx>,
-    args: GenericArgsRef<'tcx>,
-) -> GenericArgsRef<'tcx> {
-    debug!("polymorphize({:?}, {:?})", instance, args);
-    let unused = tcx.unused_generic_params(instance);
-    debug!("polymorphize: unused={:?}", unused);
-
-    // If this is a closure or coroutine then we need to handle the case where another closure
-    // from the function is captured as an upvar and hasn't been polymorphized. In this case,
-    // the unpolymorphized upvar closure would result in a polymorphized closure producing
-    // multiple mono items (and eventually symbol clashes).
-    let def_id = instance.def_id();
-    let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() {
-        ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()),
-        ty::Coroutine(..) => {
-            assert_eq!(
-                args.as_coroutine().kind_ty(),
-                tcx.types.unit,
-                "polymorphization does not support coroutines from async closures"
-            );
-            Some(args.as_coroutine().tupled_upvars_ty())
-        }
-        _ => None,
-    };
-    let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty());
-    debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
-
-    struct PolymorphizationFolder<'tcx> {
-        tcx: TyCtxt<'tcx>,
-    }
-
-    impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for PolymorphizationFolder<'tcx> {
-        fn cx(&self) -> TyCtxt<'tcx> {
-            self.tcx
-        }
-
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-            debug!("fold_ty: ty={:?}", ty);
-            match *ty.kind() {
-                ty::Closure(def_id, args) => {
-                    let polymorphized_args =
-                        polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args);
-                    if args == polymorphized_args {
-                        ty
-                    } else {
-                        Ty::new_closure(self.tcx, def_id, polymorphized_args)
-                    }
-                }
-                ty::Coroutine(def_id, args) => {
-                    let polymorphized_args =
-                        polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args);
-                    if args == polymorphized_args {
-                        ty
-                    } else {
-                        Ty::new_coroutine(self.tcx, def_id, polymorphized_args)
-                    }
-                }
-                _ => ty.super_fold_with(self),
-            }
-        }
-    }
-
-    GenericArgs::for_item(tcx, def_id, |param, _| {
-        let is_unused = unused.is_unused(param.index);
-        debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
-        match param.kind {
-            // Upvar case: If parameter is a type parameter..
-            ty::GenericParamDefKind::Type { .. } if
-                // ..and has upvars..
-                has_upvars &&
-                // ..and this param has the same type as the tupled upvars..
-                upvars_ty == Some(args[param.index as usize].expect_ty()) => {
-                    // ..then double-check that polymorphization marked it used..
-                    debug_assert!(!is_unused);
-                    // ..and polymorphize any closures/coroutines captured as upvars.
-                    let upvars_ty = upvars_ty.unwrap();
-                    let polymorphized_upvars_ty = upvars_ty.fold_with(
-                        &mut PolymorphizationFolder { tcx });
-                    debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty);
-                    ty::GenericArg::from(polymorphized_upvars_ty)
-                },
-
-            // Simple case: If parameter is a const or type parameter..
-            ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
-                // ..and is within range and unused..
-                unused.is_unused(param.index) =>
-                    // ..then use the identity for this parameter.
-                    tcx.mk_param_from_def(param),
-
-            // Otherwise, use the parameter as before.
-            _ => args[param.index as usize],
-        }
-    })
 }
 
 fn needs_fn_once_adapter_shim(
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 01ad76aedc3..07573a79260 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -552,7 +552,10 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
 
 impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
-        X86Abi { regparm: self.sess.opts.unstable_opts.regparm }
+        X86Abi {
+            regparm: self.sess.opts.unstable_opts.regparm,
+            reg_struct_return: self.sess.opts.unstable_opts.reg_struct_return,
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 142db8a17f0..474062218c9 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -978,6 +978,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
         self.async_destructor_ty(interner)
     }
+
+    fn has_unsafe_fields(self) -> bool {
+        if let ty::Adt(adt_def, ..) = self.kind() {
+            adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe)
+        } else {
+            false
+        }
+    }
 }
 
 /// Type utilities
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index e5eeb23be25..09a05104e49 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -131,8 +131,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
             VtblEntry::Vacant => continue,
             VtblEntry::Method(instance) => {
                 // Prepare the fn ptr we write into the vtable.
-                let instance = instance.polymorphize(tcx);
-                let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
+                let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT);
                 let fn_ptr = Pointer::from(fn_alloc_id);
                 Scalar::from_pointer(fn_ptr, &tcx)
             }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 3317f3b7f8a..f43c29d8f5d 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -50,6 +50,10 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx
         return construct_error(tcx, def, e);
     }
 
+    if let Err(err) = tcx.check_tail_calls(def) {
+        return construct_error(tcx, def, err);
+    }
+
     let body = match tcx.thir_body(def) {
         Err(error_reported) => construct_error(tcx, def, error_reported),
         Ok((thir, expr)) => {
diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs
new file mode 100644
index 00000000000..b1f46d37d50
--- /dev/null
+++ b/compiler/rustc_mir_build/src/check_tail_calls.rs
@@ -0,0 +1,386 @@
+use rustc_abi::ExternAbi;
+use rustc_errors::Applicability;
+use rustc_hir::LangItem;
+use rustc_hir::def::DefKind;
+use rustc_middle::span_bug;
+use rustc_middle::thir::visit::{self, Visitor};
+use rustc_middle::thir::{BodyTy, Expr, ExprId, ExprKind, Thir};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
+
+pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), ErrorGuaranteed> {
+    let (thir, expr) = tcx.thir_body(def)?;
+    let thir = &thir.borrow();
+
+    // If `thir` is empty, a type error occurred, skip this body.
+    if thir.exprs.is_empty() {
+        return Ok(());
+    }
+
+    let is_closure = matches!(tcx.def_kind(def), DefKind::Closure);
+    let caller_ty = tcx.type_of(def).skip_binder();
+
+    let mut visitor = TailCallCkVisitor {
+        tcx,
+        thir,
+        found_errors: Ok(()),
+        // FIXME(#132279): we're clearly in a body here.
+        typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
+        is_closure,
+        caller_ty,
+    };
+
+    visitor.visit_expr(&thir[expr]);
+
+    visitor.found_errors
+}
+
+struct TailCallCkVisitor<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    thir: &'a Thir<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
+    /// Whatever the currently checked body is one of a closure
+    is_closure: bool,
+    /// The result of the checks, `Err(_)` if there was a problem with some
+    /// tail call, `Ok(())` if all of them were fine.
+    found_errors: Result<(), ErrorGuaranteed>,
+    /// Type of the caller function.
+    caller_ty: Ty<'tcx>,
+}
+
+impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
+    fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
+        if self.is_closure {
+            self.report_in_closure(expr);
+            return;
+        }
+
+        let BodyTy::Fn(caller_sig) = self.thir.body_type else {
+            span_bug!(
+                call.span,
+                "`become` outside of functions should have been disallowed by hit_typeck"
+            )
+        };
+
+        let ExprKind::Scope { value, .. } = call.kind else {
+            span_bug!(call.span, "expected scope, found: {call:?}")
+        };
+        let value = &self.thir[value];
+
+        if matches!(
+            value.kind,
+            ExprKind::Binary { .. }
+                | ExprKind::Unary { .. }
+                | ExprKind::AssignOp { .. }
+                | ExprKind::Index { .. }
+        ) {
+            self.report_builtin_op(call, expr);
+            return;
+        }
+
+        let ExprKind::Call { ty, fun, ref args, from_hir_call, fn_span } = value.kind else {
+            self.report_non_call(value, expr);
+            return;
+        };
+
+        if !from_hir_call {
+            self.report_op(ty, args, fn_span, expr);
+        }
+
+        // Closures in thir look something akin to
+        // `for<'a> extern "rust-call" fn(&'a [closure@...], ()) -> <[closure@...] as FnOnce<()>>::Output {<[closure@...] as Fn<()>>::call}`
+        // So we have to check for them in this weird way...
+        if let &ty::FnDef(did, args) = ty.kind() {
+            let parent = self.tcx.parent(did);
+            if self.tcx.fn_trait_kind_from_def_id(parent).is_some()
+                && args.first().and_then(|arg| arg.as_type()).is_some_and(Ty::is_closure)
+            {
+                self.report_calling_closure(&self.thir[fun], args[1].as_type().unwrap(), expr);
+
+                // Tail calling is likely to cause unrelated errors (ABI, argument mismatches),
+                // skip them, producing an error about calling a closure is enough.
+                return;
+            };
+        }
+
+        // Erase regions since tail calls don't care about lifetimes
+        let callee_sig =
+            self.tcx.normalize_erasing_late_bound_regions(self.typing_env, ty.fn_sig(self.tcx));
+
+        if caller_sig.abi != callee_sig.abi {
+            self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
+        }
+
+        if caller_sig.inputs_and_output != callee_sig.inputs_and_output {
+            if caller_sig.inputs() != callee_sig.inputs() {
+                self.report_arguments_mismatch(expr.span, caller_sig, callee_sig);
+            }
+
+            // FIXME(explicit_tail_calls): this currenly fails for cases where opaques are used.
+            // e.g.
+            // ```
+            // fn a() -> impl Sized { become b() } // ICE
+            // fn b() -> u8 { 0 }
+            // ```
+            // we should think what is the expected behavior here.
+            // (we should probably just accept this by revealing opaques?)
+            if caller_sig.output() != callee_sig.output() {
+                span_bug!(expr.span, "hir typeck should have checked the return type already");
+            }
+        }
+
+        {
+            let caller_needs_location = self.needs_location(self.caller_ty);
+            let callee_needs_location = self.needs_location(ty);
+
+            if caller_needs_location != callee_needs_location {
+                self.report_track_caller_mismatch(expr.span, caller_needs_location);
+            }
+        }
+
+        if caller_sig.c_variadic {
+            self.report_c_variadic_caller(expr.span);
+        }
+
+        if callee_sig.c_variadic {
+            self.report_c_variadic_callee(expr.span);
+        }
+    }
+
+    /// Returns true if function of type `ty` needs location argument
+    /// (i.e. if a function is marked as `#[track_caller]`)
+    fn needs_location(&self, ty: Ty<'tcx>) -> bool {
+        if let &ty::FnDef(did, substs) = ty.kind() {
+            let instance =
+                ty::Instance::expect_resolve(self.tcx, self.typing_env, did, substs, DUMMY_SP);
+
+            instance.def.requires_caller_location(self.tcx)
+        } else {
+            false
+        }
+    }
+
+    fn report_in_closure(&mut self, expr: &Expr<'_>) {
+        let err = self.tcx.dcx().span_err(expr.span, "`become` is not allowed in closures");
+        self.found_errors = Err(err);
+    }
+
+    fn report_builtin_op(&mut self, value: &Expr<'_>, expr: &Expr<'_>) {
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(value.span, "`become` does not support operators")
+            .with_note("using `become` on a builtin operator is not useful")
+            .with_span_suggestion(
+                value.span.until(expr.span),
+                "try using `return` instead",
+                "return ",
+                Applicability::MachineApplicable,
+            )
+            .emit();
+        self.found_errors = Err(err);
+    }
+
+    fn report_op(&mut self, fun_ty: Ty<'_>, args: &[ExprId], fn_span: Span, expr: &Expr<'_>) {
+        let mut err =
+            self.tcx.dcx().struct_span_err(fn_span, "`become` does not support operators");
+
+        if let &ty::FnDef(did, _substs) = fun_ty.kind()
+            && let parent = self.tcx.parent(did)
+            && matches!(self.tcx.def_kind(parent), DefKind::Trait)
+            && let Some(method) = op_trait_as_method_name(self.tcx, parent)
+        {
+            match args {
+                &[arg] => {
+                    let arg = &self.thir[arg];
+
+                    err.multipart_suggestion(
+                        "try using the method directly",
+                        vec![
+                            (fn_span.shrink_to_lo().until(arg.span), "(".to_owned()),
+                            (arg.span.shrink_to_hi(), format!(").{method}()")),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                &[lhs, rhs] => {
+                    let lhs = &self.thir[lhs];
+                    let rhs = &self.thir[rhs];
+
+                    err.multipart_suggestion(
+                        "try using the method directly",
+                        vec![
+                            (lhs.span.shrink_to_lo(), format!("(")),
+                            (lhs.span.between(rhs.span), format!(").{method}(")),
+                            (rhs.span.between(expr.span.shrink_to_hi()), ")".to_owned()),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                _ => span_bug!(expr.span, "operator with more than 2 args? {args:?}"),
+            }
+        }
+
+        self.found_errors = Err(err.emit());
+    }
+
+    fn report_non_call(&mut self, value: &Expr<'_>, expr: &Expr<'_>) {
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(value.span, "`become` requires a function call")
+            .with_span_note(value.span, "not a function call")
+            .with_span_suggestion(
+                value.span.until(expr.span),
+                "try using `return` instead",
+                "return ",
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
+        self.found_errors = Err(err);
+    }
+
+    fn report_calling_closure(&mut self, fun: &Expr<'_>, tupled_args: Ty<'_>, expr: &Expr<'_>) {
+        let underscored_args = match tupled_args.kind() {
+            ty::Tuple(tys) if tys.is_empty() => "".to_owned(),
+            ty::Tuple(tys) => std::iter::repeat("_, ").take(tys.len() - 1).chain(["_"]).collect(),
+            _ => "_".to_owned(),
+        };
+
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(expr.span, "tail calling closures directly is not allowed")
+            .with_multipart_suggestion(
+                "try casting the closure to a function pointer type",
+                vec![
+                    (fun.span.shrink_to_lo(), "(".to_owned()),
+                    (fun.span.shrink_to_hi(), format!(" as fn({underscored_args}) -> _)")),
+                ],
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
+        self.found_errors = Err(err);
+    }
+
+    fn report_abi_mismatch(&mut self, sp: Span, caller_abi: ExternAbi, callee_abi: ExternAbi) {
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(sp, "mismatched function ABIs")
+            .with_note("`become` requires caller and callee to have the same ABI")
+            .with_note(format!("caller ABI is `{caller_abi}`, while callee ABI is `{callee_abi}`"))
+            .emit();
+        self.found_errors = Err(err);
+    }
+
+    fn report_arguments_mismatch(
+        &mut self,
+        sp: Span,
+        caller_sig: ty::FnSig<'_>,
+        callee_sig: ty::FnSig<'_>,
+    ) {
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(sp, "mismatched signatures")
+            .with_note("`become` requires caller and callee to have matching signatures")
+            .with_note(format!("caller signature: `{caller_sig}`"))
+            .with_note(format!("callee signature: `{callee_sig}`"))
+            .emit();
+        self.found_errors = Err(err);
+    }
+
+    fn report_track_caller_mismatch(&mut self, sp: Span, caller_needs_location: bool) {
+        let err = match caller_needs_location {
+            true => self
+                .tcx
+                .dcx()
+                .struct_span_err(
+                    sp,
+                    "a function marked with `#[track_caller]` cannot tail-call one that is not",
+                )
+                .emit(),
+            false => self
+                .tcx
+                .dcx()
+                .struct_span_err(
+                    sp,
+                    "a function mot marked with `#[track_caller]` cannot tail-call one that is",
+                )
+                .emit(),
+        };
+
+        self.found_errors = Err(err);
+    }
+
+    fn report_c_variadic_caller(&mut self, sp: Span) {
+        let err = self
+            .tcx
+            .dcx()
+            // FIXME(explicit_tail_calls): highlight the `...`
+            .struct_span_err(sp, "tail-calls are not allowed in c-variadic functions")
+            .emit();
+
+        self.found_errors = Err(err);
+    }
+
+    fn report_c_variadic_callee(&mut self, sp: Span) {
+        let err = self
+            .tcx
+            .dcx()
+            // FIXME(explicit_tail_calls): highlight the function or something...
+            .struct_span_err(sp, "c-variadic functions can't be tail-called")
+            .emit();
+
+        self.found_errors = Err(err);
+    }
+}
+
+impl<'a, 'tcx> Visitor<'a, 'tcx> for TailCallCkVisitor<'a, 'tcx> {
+    fn thir(&self) -> &'a Thir<'tcx> {
+        &self.thir
+    }
+
+    fn visit_expr(&mut self, expr: &'a Expr<'tcx>) {
+        if let ExprKind::Become { value } = expr.kind {
+            let call = &self.thir[value];
+            self.check_tail_call(call, expr);
+        }
+
+        visit::walk_expr(self, expr);
+    }
+}
+
+fn op_trait_as_method_name(tcx: TyCtxt<'_>, trait_did: DefId) -> Option<&'static str> {
+    let m = match tcx.as_lang_item(trait_did)? {
+        LangItem::Add => "add",
+        LangItem::Sub => "sub",
+        LangItem::Mul => "mul",
+        LangItem::Div => "div",
+        LangItem::Rem => "rem",
+        LangItem::Neg => "neg",
+        LangItem::Not => "not",
+        LangItem::BitXor => "bitxor",
+        LangItem::BitAnd => "bitand",
+        LangItem::BitOr => "bitor",
+        LangItem::Shl => "shl",
+        LangItem::Shr => "shr",
+        LangItem::AddAssign => "add_assign",
+        LangItem::SubAssign => "sub_assign",
+        LangItem::MulAssign => "mul_assign",
+        LangItem::DivAssign => "div_assign",
+        LangItem::RemAssign => "rem_assign",
+        LangItem::BitXorAssign => "bitxor_assign",
+        LangItem::BitAndAssign => "bitand_assign",
+        LangItem::BitOrAssign => "bitor_assign",
+        LangItem::ShlAssign => "shl_assign",
+        LangItem::ShrAssign => "shr_assign",
+        LangItem::Index => "index",
+        LangItem::IndexMut => "index_mut",
+        _ => return None,
+    };
+
+    Some(m)
+}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 3dbb552cdbb..833e5019865 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -12,6 +12,7 @@
 // tidy-alphabetical-end
 
 mod build;
+mod check_tail_calls;
 mod check_unsafety;
 mod errors;
 pub mod lints;
@@ -28,6 +29,7 @@ pub fn provide(providers: &mut Providers) {
     providers.closure_saved_names_of_captured_variables =
         build::closure_saved_names_of_captured_variables;
     providers.check_unsafety = check_unsafety::check_unsafety;
+    providers.check_tail_calls = check_tail_calls::check_tail_calls;
     providers.thir_body = thir::cx::thir_body;
     providers.hooks.thir_tree = thir::print::thir_tree;
     providers.hooks.thir_flat = thir::print::thir_flat;
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 3fa0e4def82..30b6718683b 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -2,7 +2,7 @@ use rustc_ast as ast;
 use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
-use rustc_middle::ty::{self, ScalarInt, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
 use tracing::trace;
 
 use crate::build::parse_float_into_scalar;
@@ -13,6 +13,10 @@ pub(crate) fn lit_to_const<'tcx>(
 ) -> Result<ty::Const<'tcx>, LitToConstError> {
     let LitToConstInput { lit, ty, neg } = lit_input;
 
+    if let Err(guar) = ty.error_reported() {
+        return Ok(ty::Const::new_error(tcx, guar));
+    }
+
     let trunc = |n| {
         let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
             Ok(layout) => layout.size,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 3ac53fa6272..2dbc8b7b573 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -626,32 +626,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     ) -> PatKind<'tcx> {
         let tcx = self.tcx;
         let def_id = block.def_id;
-        let body_id = block.body;
-        let expr = &tcx.hir().body(body_id).value;
         let ty = tcx.typeck(def_id).node_type(block.hir_id);
 
-        // Special case inline consts that are just literals. This is solely
-        // a performance optimization, as we could also just go through the regular
-        // const eval path below.
-        // FIXME: investigate the performance impact of removing this.
-        let lit_input = match expr.kind {
-            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
-            hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
-                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
-                _ => None,
-            },
-            _ => None,
-        };
-        if let Some(lit_input) = lit_input {
-            match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return self.const_to_pat(c, ty, id, span).kind,
-                // If an error occurred, ignore that it's a literal
-                // and leave reporting the error up to const eval of
-                // the unevaluated constant below.
-                Err(_) => {}
-            }
-        }
-
         let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
         let parent_args =
             tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 8528a2e68c0..540ce7cc4ce 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -41,6 +41,4 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
 monomorphize_unknown_cgu_collection_mode =
     unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
 
-monomorphize_unused_generic_params = item has unused generic parameters
-
 monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 5efe7ffc7b9..480d82c1a38 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -965,9 +965,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
         return true;
     }
 
-    if tcx.is_reachable_non_generic(def_id)
-        || instance.polymorphize(*tcx).upstream_monomorphization(*tcx).is_some()
-    {
+    if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(*tcx).is_some() {
         // We can link to the item in question, no instance needed in this crate.
         return false;
     }
@@ -1114,7 +1112,7 @@ fn create_fn_mono_item<'tcx>(
         crate::util::dump_closure_profile(tcx, instance);
     }
 
-    respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
+    respan(source, MonoItem::Fn(instance))
 }
 
 /// Creates a `MonoItem` for each method that is referenced by the vtable for
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 02865cad302..fc8d63b5888 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,11 +1,8 @@
 use std::path::PathBuf;
 
-use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::{Diagnostic, LintDiagnostic};
 use rustc_span::{Span, Symbol};
 
-use crate::fluent_generated as fluent;
-
 #[derive(Diagnostic)]
 #[diag(monomorphize_recursion_limit)]
 pub(crate) struct RecursionLimit {
@@ -28,28 +25,6 @@ pub(crate) struct NoOptimizedMir {
     pub crate_name: Symbol,
 }
 
-pub(crate) struct UnusedGenericParamsHint {
-    pub span: Span,
-    pub param_spans: Vec<Span>,
-    pub param_names: Vec<String>,
-}
-
-impl<G: EmissionGuarantee> Diagnostic<'_, G> for UnusedGenericParamsHint {
-    #[track_caller]
-    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
-        let mut diag = Diag::new(dcx, level, fluent::monomorphize_unused_generic_params);
-        diag.span(self.span);
-        for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
-            // FIXME: I can figure out how to do a label with a fluent string with a fixed message,
-            // or a label with a dynamic value in a hard-coded string, but I haven't figured out
-            // how to combine the two. 😢
-            #[allow(rustc::untranslatable_diagnostic)]
-            diag.span_label(span, format!("generic parameter `{name}` is unused"));
-        }
-        diag
-    }
-}
-
 #[derive(LintDiagnostic)]
 #[diag(monomorphize_large_assignments)]
 #[note]
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 0f08930fb4c..caae54cd559 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -19,7 +19,6 @@ mod collector;
 mod errors;
 mod mono_checks;
 mod partitioning;
-mod polymorphize;
 mod util;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@@ -50,6 +49,5 @@ fn custom_coerce_unsize_info<'tcx>(
 
 pub fn provide(providers: &mut Providers) {
     partitioning::provide(providers);
-    polymorphize::provide(providers);
     mono_checks::provide(providers);
 }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 7ea4ded2b05..dabce72650a 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -113,7 +113,6 @@ use rustc_middle::mir::mono::{
     Visibility,
 };
 use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
-use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, InstanceKind, TyCtxt};
 use rustc_middle::util::Providers;
 use rustc_session::CodegenUnits;
@@ -661,18 +660,14 @@ fn characteristic_def_id_of_mono_item<'tcx>(
                     return None;
                 }
 
-                // When polymorphization is enabled, methods which do not depend on their generic
-                // parameters, but the self-type of their impl block do will fail to normalize.
-                if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() {
-                    // This is a method within an impl, find out what the self-type is:
-                    let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions(
-                        instance.args,
-                        ty::TypingEnv::fully_monomorphized(),
-                        tcx.type_of(impl_def_id),
-                    );
-                    if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
-                        return Some(def_id);
-                    }
+                // This is a method within an impl, find out what the self-type is:
+                let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions(
+                    instance.args,
+                    ty::TypingEnv::fully_monomorphized(),
+                    tcx.type_of(impl_def_id),
+                );
+                if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
+                    return Some(def_id);
                 }
             }
 
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
deleted file mode 100644
index e049fe99664..00000000000
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ /dev/null
@@ -1,334 +0,0 @@
-//! Polymorphization Analysis
-//! =========================
-//!
-//! This module implements an analysis of functions, methods and closures to determine which
-//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
-//! for their size, offset of a field, etc.).
-
-use rustc_hir::ConstContext;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_middle::mir::visit::{TyContext, Visitor};
-use rustc_middle::mir::{self, Local, LocalDecl, Location};
-use rustc_middle::query::Providers;
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams};
-use rustc_span::symbol::sym;
-use tracing::{debug, instrument};
-
-use crate::errors::UnusedGenericParamsHint;
-
-/// Provide implementations of queries relating to polymorphization analysis.
-pub(crate) fn provide(providers: &mut Providers) {
-    providers.unused_generic_params = unused_generic_params;
-}
-
-/// Determine which generic parameters are used by the instance.
-///
-/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all
-/// parameters are used).
-fn unused_generic_params<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    instance: ty::InstanceKind<'tcx>,
-) -> UnusedGenericParams {
-    assert!(instance.def_id().is_local());
-
-    if !tcx.sess.opts.unstable_opts.polymorphize {
-        // If polymorphization disabled, then all parameters are used.
-        return UnusedGenericParams::new_all_used();
-    }
-
-    let def_id = instance.def_id();
-    // Exit early if this instance should not be polymorphized.
-    if !should_polymorphize(tcx, def_id, instance) {
-        return UnusedGenericParams::new_all_used();
-    }
-
-    let generics = tcx.generics_of(def_id);
-    debug!(?generics);
-
-    // Exit early when there are no parameters to be unused.
-    if generics.is_empty() {
-        return UnusedGenericParams::new_all_used();
-    }
-
-    // Create a bitset with N rightmost ones for each parameter.
-    let generics_count: u32 =
-        generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
-    let mut unused_parameters = UnusedGenericParams::new_all_unused(generics_count);
-    debug!(?unused_parameters, "(start)");
-
-    mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
-    debug!(?unused_parameters, "(after default)");
-
-    // Visit MIR and accumulate used generic parameters.
-    let body = match tcx.hir().body_const_context(def_id.expect_local()) {
-        // Const functions are actually called and should thus be considered for polymorphization
-        // via their runtime MIR.
-        Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id),
-        Some(_) => tcx.mir_for_ctfe(def_id),
-    };
-    let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
-    vis.visit_body(body);
-    debug!(?unused_parameters, "(end)");
-
-    // Emit errors for debugging and testing if enabled.
-    if !unused_parameters.all_used() {
-        emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters);
-    }
-
-    unused_parameters
-}
-
-/// Returns `true` if the instance should be polymorphized.
-fn should_polymorphize<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    instance: ty::InstanceKind<'tcx>,
-) -> bool {
-    // If an instance's MIR body is not polymorphic then the modified generic parameters that are
-    // derived from polymorphization's result won't make any difference.
-    if !instance.has_polymorphic_mir_body() {
-        return false;
-    }
-
-    // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic.
-    if matches!(instance, ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::Virtual(..)) {
-        return false;
-    }
-
-    // Foreign items have no bodies to analyze.
-    if tcx.is_foreign_item(def_id) {
-        return false;
-    }
-
-    // Make sure there is MIR available.
-    match tcx.hir().body_const_context(def_id.expect_local()) {
-        Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
-            debug!("no mir available");
-            return false;
-        }
-        Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
-            debug!("no ctfe mir available");
-            return false;
-        }
-        _ => true,
-    }
-}
-
-/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
-/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
-/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
-#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))]
-fn mark_used_by_default_parameters<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    generics: &'tcx ty::Generics,
-    unused_parameters: &mut UnusedGenericParams,
-) {
-    match tcx.def_kind(def_id) {
-        DefKind::Closure | DefKind::SyntheticCoroutineBody => {
-            for param in &generics.own_params {
-                debug!(?param, "(closure/gen)");
-                unused_parameters.mark_used(param.index);
-            }
-        }
-        DefKind::Mod
-        | DefKind::Struct
-        | DefKind::Union
-        | DefKind::Enum
-        | DefKind::Variant
-        | DefKind::Trait
-        | DefKind::TyAlias
-        | DefKind::ForeignTy
-        | DefKind::TraitAlias
-        | DefKind::AssocTy
-        | DefKind::TyParam
-        | DefKind::Fn
-        | DefKind::Const
-        | DefKind::ConstParam
-        | DefKind::Static { .. }
-        | DefKind::Ctor(_, _)
-        | DefKind::AssocFn
-        | DefKind::AssocConst
-        | DefKind::Macro(_)
-        | DefKind::ExternCrate
-        | DefKind::Use
-        | DefKind::ForeignMod
-        | DefKind::AnonConst
-        | DefKind::InlineConst
-        | DefKind::OpaqueTy
-        | DefKind::Field
-        | DefKind::LifetimeParam
-        | DefKind::GlobalAsm
-        | DefKind::Impl { .. } => {
-            for param in &generics.own_params {
-                debug!(?param, "(other)");
-                if let ty::GenericParamDefKind::Lifetime = param.kind {
-                    unused_parameters.mark_used(param.index);
-                }
-            }
-        }
-    }
-
-    if let Some(parent) = generics.parent {
-        mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters);
-    }
-}
-
-/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
-/// parameter which was unused.
-#[instrument(level = "debug", skip(tcx, generics))]
-fn emit_unused_generic_params_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    generics: &'tcx ty::Generics,
-    unused_parameters: &UnusedGenericParams,
-) {
-    let base_def_id = tcx.typeck_root_def_id(def_id);
-    if !tcx.has_attr(base_def_id, sym::rustc_polymorphize_error) {
-        return;
-    }
-
-    let fn_span = match tcx.opt_item_ident(def_id) {
-        Some(ident) => ident.span,
-        _ => tcx.def_span(def_id),
-    };
-
-    let mut param_spans = Vec::new();
-    let mut param_names = Vec::new();
-    let mut next_generics = Some(generics);
-    while let Some(generics) = next_generics {
-        for param in &generics.own_params {
-            if unused_parameters.is_unused(param.index) {
-                debug!(?param);
-                let def_span = tcx.def_span(param.def_id);
-                param_spans.push(def_span);
-                param_names.push(param.name.to_string());
-            }
-        }
-
-        next_generics = generics.parent.map(|did| tcx.generics_of(did));
-    }
-
-    tcx.dcx().emit_err(UnusedGenericParamsHint { span: fn_span, param_spans, param_names });
-}
-
-/// Visitor used to aggregate generic parameter uses.
-struct MarkUsedGenericParams<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    unused_parameters: &'a mut UnusedGenericParams,
-}
-
-impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
-    /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
-    /// a closure, coroutine or constant).
-    #[instrument(level = "debug", skip(self, def_id, args))]
-    fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
-        let instance = ty::InstanceKind::Item(def_id);
-        let unused = self.tcx.unused_generic_params(instance);
-        debug!(?self.unused_parameters, ?unused);
-        for (i, arg) in args.iter().enumerate() {
-            let i = i.try_into().unwrap();
-            if unused.is_used(i) {
-                arg.visit_with(self);
-            }
-        }
-        debug!(?self.unused_parameters);
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
-    #[instrument(level = "debug", skip(self, local))]
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        if local == Local::from_usize(1) {
-            let def_kind = self.tcx.def_kind(self.def_id);
-            if matches!(def_kind, DefKind::Closure) {
-                // Skip visiting the closure/coroutine that is currently being processed. This only
-                // happens because the first argument to the closure is a reference to itself and
-                // that will call `visit_args`, resulting in each generic parameter captured being
-                // considered used by default.
-                debug!("skipping closure args");
-                return;
-            }
-        }
-
-        self.super_local_decl(local, local_decl);
-    }
-
-    fn visit_const_operand(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
-        match ct.const_ {
-            mir::Const::Ty(_, c) => {
-                c.visit_with(self);
-            }
-            mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
-                // Avoid considering `T` unused when constants are of the form:
-                //   `<Self as Foo<T>>::foo::promoted[p]`
-                if let Some(p) = promoted {
-                    if self.def_id == def && !self.tcx.generics_of(def).has_self {
-                        // If there is a promoted, don't look at the args - since it will always contain
-                        // the generic parameters, instead, traverse the promoted MIR.
-                        let promoted = self.tcx.promoted_mir(def);
-                        self.visit_body(&promoted[p]);
-                    }
-                }
-
-                Visitor::visit_ty(self, ty, TyContext::Location(location));
-            }
-            mir::Const::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)),
-        }
-    }
-
-    fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
-        ty.visit_with(self);
-    }
-}
-
-impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
-    #[instrument(level = "debug", skip(self))]
-    fn visit_const(&mut self, c: ty::Const<'tcx>) {
-        if !c.has_non_region_param() {
-            return;
-        }
-
-        match c.kind() {
-            ty::ConstKind::Param(param) => {
-                debug!(?param);
-                self.unused_parameters.mark_used(param.index);
-            }
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args })
-                if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
-            {
-                self.visit_child_body(def, args);
-            }
-            _ => c.super_visit_with(self),
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_ty(&mut self, ty: Ty<'tcx>) {
-        if !ty.has_non_region_param() {
-            return;
-        }
-
-        match *ty.kind() {
-            ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
-                debug!(?def_id);
-                // Avoid cycle errors with coroutines.
-                if def_id == self.def_id {
-                    return;
-                }
-
-                // Consider any generic parameters used by any closures/coroutines as used in the
-                // parent.
-                self.visit_child_body(def_id, args);
-            }
-            ty::Param(param) => {
-                debug!(?param);
-                self.unused_parameters.mark_used(param.index);
-            }
-            _ => ty.super_visit_with(self),
-        }
-    }
-}
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 6641d2bf924..12df35d30b8 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -169,6 +169,14 @@ where
             return result;
         }
 
+        // Only consider auto impls of unsafe traits when there are no unsafe
+        // fields.
+        if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
+            && goal.predicate.self_ty().has_unsafe_fields()
+        {
+            return Err(NoSolution);
+        }
+
         // We only look into opaque types during analysis for opaque types
         // outside of their defining scope. Doing so for opaques in the
         // defining scope may require calling `typeck` on the same item we're
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index 8fd87893a98..eb14b78a003 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -135,5 +135,6 @@ session_unsupported_crate_type_for_target =
 
 session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
 
+session_unsupported_reg_struct_return_arch = `-Zreg-struct-return` is only supported on x86
 session_unsupported_regparm = `-Zregparm={$regparm}` is unsupported (valid values 0-3)
 session_unsupported_regparm_arch = `-Zregparm=N` is only supported on x86
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 736a5ce0704..6c26a781487 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -490,6 +490,10 @@ pub(crate) struct UnsupportedRegparm {
 pub(crate) struct UnsupportedRegparmArch;
 
 #[derive(Diagnostic)]
+#[diag(session_unsupported_reg_struct_return_arch)]
+pub(crate) struct UnsupportedRegStructReturnArch;
+
+#[derive(Diagnostic)]
 #[diag(session_failed_to_create_profiler)]
 pub(crate) struct FailedToCreateProfiler {
     pub(crate) err: String,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 2c0302bbb2b..b01d9e5e8e3 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1950,8 +1950,6 @@ options! {
         (default: PLT is disabled if full relro is enabled on x86_64)"),
     polonius: Polonius = (Polonius::default(), parse_polonius, [TRACKED],
         "enable polonius-based borrow-checker (default: no)"),
-    polymorphize: bool = (false, parse_bool, [TRACKED],
-          "perform polymorphization analysis"),
     pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED],
         "a single extra argument to prepend the linker invocation (can be used several times)"),
     pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
@@ -1988,6 +1986,9 @@ options! {
         "enable queries of the dependency graph for regression testing (default: no)"),
     randomize_layout: bool = (false, parse_bool, [TRACKED],
         "randomize the layout of types (default: no)"),
+    reg_struct_return: bool = (false, parse_bool, [TRACKED],
+        "On x86-32 targets, it overrides the default ABI to return small structs in registers.
+        It is UNSOUND to link together crates that use different values for this flag!"),
     regparm: Option<u32> = (None, parse_opt_number, [TRACKED],
         "On x86-32 targets, setting this to N causes the compiler to pass N arguments \
         in registers EAX, EDX, and ECX instead of on the stack for\
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 120ae9946ea..7db3b7b7d9d 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1305,6 +1305,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
             sess.dcx().emit_err(errors::UnsupportedRegparmArch);
         }
     }
+    if sess.opts.unstable_opts.reg_struct_return {
+        if sess.target.arch != "x86" {
+            sess.dcx().emit_err(errors::UnsupportedRegStructReturnArch);
+        }
+    }
 
     // The code model check applies to `thunk` and `thunk-extern`, but not `thunk-inline`, so it is
     // kept as a `match` to force a change if new ones are added, even if we currently only support
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 47ceab750cf..a7dc20a874b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1746,7 +1746,6 @@ symbols! {
         rustc_peek_liveness,
         rustc_peek_maybe_init,
         rustc_peek_maybe_uninit,
-        rustc_polymorphize_error,
         rustc_preserve_ub_checks,
         rustc_private,
         rustc_proc_macro_decls,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index dcbc5f0f76d..1a10ab8829c 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -256,7 +256,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         });
 
         // Encode impl generic params if the generic parameters contain non-region parameters
-        // (implying polymorphization is enabled) and this isn't an inherent impl.
+        // and this isn't an inherent impl.
         if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
             self.path_generic_args(
                 |this| {
@@ -330,9 +330,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Float(FloatTy::F128) => "C4f128",
             ty::Never => "z",
 
-            // Should only be encountered with polymorphization,
-            // or within the identity-substituted impl header of an
-            // item nested within an impl item.
+            // Should only be encountered within the identity-substituted
+            // impl header of an item nested within an impl item.
             ty::Param(_) => "p",
 
             ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => bug!(),
@@ -558,9 +557,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         let (ct_ty, valtree) = match ct.kind() {
             ty::ConstKind::Value(ty, val) => (ty, val),
 
-            // Should only be encountered with polymorphization,
-            // or within the identity-substituted impl header of an
-            // item nested within an impl item.
+            // Should only be encountered within the identity-substituted
+            // impl header of an item nested within an impl item.
             ty::ConstKind::Param(_) => {
                 // Never cached (single-character).
                 self.push("p");
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index fb0fe402934..746e8173807 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -661,7 +661,9 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                     }
                     _ => (x86::Flavor::General, None),
                 };
-                x86::compute_abi_info(cx, self, x86::X86Options { flavor, regparm });
+                let reg_struct_return = cx.x86_abi_opt().reg_struct_return;
+                let opts = x86::X86Options { flavor, regparm, reg_struct_return };
+                x86::compute_abi_info(cx, self, opts);
             }
             "x86_64" => match abi {
                 spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs
index a5af975d4d2..cd8465c09ca 100644
--- a/compiler/rustc_target/src/callconv/x86.rs
+++ b/compiler/rustc_target/src/callconv/x86.rs
@@ -14,6 +14,7 @@ pub(crate) enum Flavor {
 pub(crate) struct X86Options {
     pub flavor: Flavor,
     pub regparm: Option<u32>,
+    pub reg_struct_return: bool,
 }
 
 pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options)
@@ -31,7 +32,7 @@ where
             // https://www.angelcode.com/dev/callconv/callconv.html
             // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
             let t = cx.target_spec();
-            if t.abi_return_struct_as_int {
+            if t.abi_return_struct_as_int || opts.reg_struct_return {
                 // According to Clang, everyone but MSVC returns single-element
                 // float aggregates directly in a floating-point register.
                 if !t.is_like_msvc && fn_abi.ret.layout.is_single_fp_element(cx) {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index a2e9430830a..210d67fa1aa 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2117,6 +2117,8 @@ pub struct X86Abi {
     /// On x86-32 targets, the regparm N causes the compiler to pass arguments
     /// in registers EAX, EDX, and ECX instead of on the stack.
     pub regparm: Option<u32>,
+    /// Override the default ABI to return small structs in registers
+    pub reg_struct_return: bool,
 }
 
 pub trait HasX86AbiOpt {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 32b4567aba4..3e2c8467d32 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -18,6 +18,7 @@ use rustc_infer::traits::{
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
+use rustc_type_ir::Interner;
 use tracing::{debug, instrument, trace};
 
 use super::SelectionCandidate::*;
@@ -794,6 +795,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::Never
                 | ty::Tuple(_)
                 | ty::CoroutineWitness(..) => {
+                    use rustc_type_ir::inherent::*;
+
+                    // Only consider auto impls of unsafe traits when there are
+                    // no unsafe fields.
+                    if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
+                        return;
+                    }
+
                     // Only consider auto impls if there are no manual impls for the root of `self_ty`.
                     //
                     // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index b746d6299ef..ae6d697794f 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -45,23 +45,8 @@ fn fn_sig_for_fn_abi<'tcx>(
     let ty = instance.ty(tcx, typing_env);
     match *ty.kind() {
         ty::FnDef(def_id, args) => {
-            // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
-            // parameters unused if they show up in the signature, but not in the `mir::Body`
-            // (i.e. due to being inside a projection that got normalized, see
-            // `tests/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
-            // track of a polymorphization `ParamEnv` to allow normalizing later.
-            //
-            // We normalize the `fn_sig` again after instantiating at a later point.
-            let mut sig = tcx.instantiate_bound_regions_with_erased(
-                tcx.fn_sig(def_id)
-                    .map_bound(|fn_sig| {
-                        tcx.normalize_erasing_regions(
-                            ty::TypingEnv::non_body_analysis(tcx, def_id),
-                            fn_sig,
-                        )
-                    })
-                    .instantiate(tcx, args),
-            );
+            let mut sig = tcx
+                .instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args));
 
             if let ty::InstanceKind::VTableShim(..) = instance.def {
                 let mut inputs_and_output = sig.inputs_and_output.to_vec();
@@ -473,20 +458,30 @@ fn fn_abi_sanity_check<'tcx>(
                         // This really shouldn't happen even for sized aggregates, since
                         // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
                         // LLVM type. This means all sorts of Rust type details leak into the ABI.
-                        // However wasm sadly *does* currently use this mode so we have to allow it --
-                        // but we absolutely shouldn't let any more targets do that.
-                        // (Also see <https://github.com/rust-lang/rust/issues/115666>.)
+                        // However wasm sadly *does* currently use this mode for it's "C" ABI so we
+                        // have to allow it -- but we absolutely shouldn't let any more targets do
+                        // that. (Also see <https://github.com/rust-lang/rust/issues/115666>.)
                         //
                         // The unstable abi `PtxKernel` also uses Direct for now.
                         // It needs to switch to something else before stabilization can happen.
                         // (See issue: https://github.com/rust-lang/rust/issues/117271)
-                        assert!(
-                            matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64")
-                                || matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted),
-                            "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
-                          Problematic type: {:#?}",
-                            arg.layout,
-                        );
+                        //
+                        // And finally the unadjusted ABI is ill specified and uses Direct for all
+                        // args, but unfortunately we need it for calling certain LLVM intrinsics.
+
+                        match spec_abi {
+                            ExternAbi::Unadjusted => {}
+                            ExternAbi::PtxKernel => {}
+                            ExternAbi::C { unwind: _ }
+                                if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {}
+                            _ => {
+                                panic!(
+                                    "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
+                                      Problematic type: {:#?}",
+                                    arg.layout,
+                                );
+                            }
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index a201f2b1c11..f45c94127bd 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -136,6 +136,9 @@ pub trait Ty<I: Interner<Ty = Self>>:
         matches!(self.kind(), ty::FnPtr(..))
     }
 
+    /// Checks whether this type is an ADT that has unsafe fields.
+    fn has_unsafe_fields(self) -> bool;
+
     fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
         match self.kind() {
             ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 0ae688848eb..025ec7ae896 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -270,6 +270,9 @@ pub trait Interner:
 
     fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
 
+    /// Returns `true` if this is an `unsafe trait`.
+    fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool;
+
     fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
 
     fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index 695dddb25ee..e40de13f3d4 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -596,6 +596,8 @@ pub use core::fmt::{Arguments, write};
 pub use core::fmt::{Binary, Octal};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::fmt::{Debug, Display};
+#[unstable(feature = "formatting_options", issue = "118117")]
+pub use core::fmt::{DebugAsHex, FormattingOptions, Sign};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 84f4202c02a..927c3aa23b9 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -117,6 +117,7 @@
 #![feature(extend_one_unchecked)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
+#![feature(formatting_options)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index e0576c25515..c5378d78d59 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2682,7 +2682,8 @@ impl<T: fmt::Display + ?Sized> ToString for T {
     #[inline]
     default fn to_string(&self) -> String {
         let mut buf = String::new();
-        let mut formatter = core::fmt::Formatter::new(&mut buf);
+        let mut formatter =
+            core::fmt::Formatter::new(&mut buf, core::fmt::FormattingOptions::new());
         // Bypass format_args!() to avoid write_str with zero-length strs
         fmt::Display::fmt(self, &mut formatter)
             .expect("a Display implementation returned an error unexpectedly");
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index 0f8e74300a4..b4116f4988b 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -199,7 +199,6 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
 ///
 /// ```rust
 /// #![feature(local_waker)]
-/// #![feature(noop_waker)]
 /// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker};
 /// use std::future::Future;
 /// use std::pin::Pin;
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 4b706086e07..457be3ae77f 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -3025,26 +3025,29 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
         self.spec_extend(other.iter())
     }
 
-    /// Copies elements from `src` range to the end of the vector.
+    /// Given a range `src`, clones a slice of elements in that range and appends it to the end.
+    ///
+    /// `src` must be a range that can form a valid subslice of the `Vec`.
     ///
     /// # Panics
     ///
-    /// Panics if the starting point is greater than the end point or if
-    /// the end point is greater than the length of the vector.
+    /// Panics if starting index is greater than the end index
+    /// or if the index is greater than the length of the vector.
     ///
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![0, 1, 2, 3, 4];
-    ///
-    /// vec.extend_from_within(2..);
-    /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]);
+    /// let mut characters = vec!['a', 'b', 'c', 'd', 'e'];
+    /// characters.extend_from_within(2..);
+    /// assert_eq!(characters, ['a', 'b', 'c', 'd', 'e', 'c', 'd', 'e']);
     ///
-    /// vec.extend_from_within(..2);
-    /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]);
+    /// let mut numbers = vec![0, 1, 2, 3, 4];
+    /// numbers.extend_from_within(..2);
+    /// assert_eq!(numbers, [0, 1, 2, 3, 4, 0, 1]);
     ///
-    /// vec.extend_from_within(4..8);
-    /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]);
+    /// let mut strings = vec![String::from("hello"), String::from("world"), String::from("!")];
+    /// strings.extend_from_within(1..=2);
+    /// assert_eq!(strings, ["hello", "world", "!", "world", "!"]);
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "vec_extend_from_within", since = "1.53.0")]
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 04230b1610a..3f10158193d 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -86,7 +86,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.precision {
+    if let Some(precision) = fmt.options.precision {
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
         let min_precision = 0;
@@ -162,7 +162,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.precision {
+    if let Some(precision) = fmt.options.precision {
         // 1 integral digit + `precision` fractional digits = `precision + 1` total digits
         float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
     } else {
@@ -180,7 +180,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.precision {
+    if let Some(precision) = fmt.options.precision {
         // this behavior of {:.PREC?} predates exponential formatting for {:?}
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 7fc9dd21fdd..14c70065101 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -33,6 +33,19 @@ pub enum Alignment {
     Center,
 }
 
+#[doc(hidden)]
+#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
+impl From<rt::Alignment> for Option<Alignment> {
+    fn from(value: rt::Alignment) -> Self {
+        match value {
+            rt::Alignment::Left => Some(Alignment::Left),
+            rt::Alignment::Right => Some(Alignment::Right),
+            rt::Alignment::Center => Some(Alignment::Center),
+            rt::Alignment::Unknown => None,
+        }
+    }
+}
+
 #[stable(feature = "debug_builders", since = "1.2.0")]
 pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 #[unstable(feature = "debug_closure_helpers", issue = "117729")]
@@ -247,6 +260,251 @@ impl<W: Write + ?Sized> Write for &mut W {
     }
 }
 
+/// The signedness of a [`Formatter`] (or of a [`FormattingOptions`]).
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[unstable(feature = "formatting_options", issue = "118117")]
+pub enum Sign {
+    /// Represents the `+` flag.
+    Plus,
+    /// Represents the `-` flag.
+    Minus,
+}
+
+/// Specifies whether the [`Debug`] trait should use lower-/upper-case
+/// hexadecimal or normal integers.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[unstable(feature = "formatting_options", issue = "118117")]
+pub enum DebugAsHex {
+    /// Use lower-case hexadecimal integers for the `Debug` trait (like [the `x?` type](../../std/fmt/index.html#formatting-traits)).
+    Lower,
+    /// Use upper-case hexadecimal integers for the `Debug` trait (like [the `X?` type](../../std/fmt/index.html#formatting-traits)).
+    Upper,
+}
+
+/// Options for formatting.
+///
+/// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait.
+/// It is mainly used to construct `Formatter` instances.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
+#[unstable(feature = "formatting_options", issue = "118117")]
+pub struct FormattingOptions {
+    flags: u32,
+    fill: char,
+    align: Option<Alignment>,
+    width: Option<usize>,
+    precision: Option<usize>,
+}
+
+impl FormattingOptions {
+    /// Construct a new `FormatterBuilder` with the supplied `Write` trait
+    /// object for output that is equivalent to the `{}` formatting
+    /// specifier:
+    ///
+    /// - no flags,
+    /// - filled with spaces,
+    /// - no alignment,
+    /// - no width,
+    /// - no precision, and
+    /// - no [`DebugAsHex`] output mode.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn new() -> Self {
+        Self { flags: 0, fill: ' ', align: None, width: None, precision: None }
+    }
+
+    /// Sets or removes the sign (the `+` or the `-` flag).
+    ///
+    /// - `+`: This is intended for numeric types and indicates that the sign
+    /// should always be printed. By default only the negative sign of signed
+    /// values is printed, and the sign of positive or unsigned values is
+    /// omitted. This flag indicates that the correct sign (+ or -) should
+    /// always be printed.
+    /// - `-`: Currently not used
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
+        self.flags =
+            self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32);
+        match sign {
+            None => {}
+            Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32,
+            Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32,
+        }
+        self
+    }
+    /// Sets or unsets the `0` flag.
+    ///
+    /// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
+        if sign_aware_zero_pad {
+            self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32
+        } else {
+            self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32)
+        }
+        self
+    }
+    /// Sets or unsets the `#` flag.
+    ///
+    /// This flag indicates that the "alternate" form of printing should be
+    /// used. The alternate forms are:
+    /// - [`Debug`] : pretty-print the [`Debug`] formatting (adds linebreaks and indentation)
+    /// - [`LowerHex`] as well as [`UpperHex`] - precedes the argument with a `0x`
+    /// - [`Octal`] - precedes the argument with a `0b`
+    /// - [`Binary`] - precedes the argument with a `0o`
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn alternate(&mut self, alternate: bool) -> &mut Self {
+        if alternate {
+            self.flags |= 1 << rt::Flag::Alternate as u32
+        } else {
+            self.flags &= !(1 << rt::Flag::Alternate as u32)
+        }
+        self
+    }
+    /// Sets the fill character.
+    ///
+    /// The optional fill character and alignment is provided normally in
+    /// conjunction with the width parameter. This indicates that if the value
+    /// being formatted is smaller than width some extra characters will be
+    /// printed around it.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn fill(&mut self, fill: char) -> &mut Self {
+        self.fill = fill;
+        self
+    }
+    /// Sets or removes the alignment.
+    ///
+    /// The alignment specifies how the value being formatted should be
+    /// positioned if it is smaller than the width of the formatter.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
+        self.align = align;
+        self
+    }
+    /// Sets or removes the width.
+    ///
+    /// This is a parameter for the “minimum width” that the format should take
+    /// up. If the value’s string does not fill up this many characters, then
+    /// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
+    /// will be used to take up the required space.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn width(&mut self, width: Option<usize>) -> &mut Self {
+        self.width = width;
+        self
+    }
+    /// Sets or removes the precision.
+    ///
+    /// - For non-numeric types, this can be considered a “maximum width”. If
+    /// the resulting string is longer than this width, then it is truncated
+    /// down to this many characters and that truncated value is emitted with
+    /// proper fill, alignment and width if those parameters are set.
+    /// - For integral types, this is ignored.
+    /// - For floating-point types, this indicates how many digits after the
+    /// decimal point should be printed.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn precision(&mut self, precision: Option<usize>) -> &mut Self {
+        self.precision = precision;
+        self
+    }
+    /// Specifies whether the [`Debug`] trait should use lower-/upper-case
+    /// hexadecimal or normal integers
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
+        self.flags = self.flags
+            & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32);
+        match debug_as_hex {
+            None => {}
+            Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32,
+            Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32,
+        }
+        self
+    }
+
+    /// Returns the current sign (the `+` or the `-` flag).
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_sign(&self) -> Option<Sign> {
+        const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32;
+        const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32;
+        match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) {
+            SIGN_PLUS_BITFIELD => Some(Sign::Plus),
+            SIGN_MINUS_BITFIELD => Some(Sign::Minus),
+            0 => None,
+            _ => panic!("Invalid sign bits set in flags"),
+        }
+    }
+    /// Returns the current `0` flag.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_sign_aware_zero_pad(&self) -> bool {
+        self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+    }
+    /// Returns the current `#` flag.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_alternate(&self) -> bool {
+        self.flags & (1 << rt::Flag::Alternate as u32) != 0
+    }
+    /// Returns the current fill character.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_fill(&self) -> char {
+        self.fill
+    }
+    /// Returns the current alignment.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_align(&self) -> Option<Alignment> {
+        self.align
+    }
+    /// Returns the current width.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_width(&self) -> Option<usize> {
+        self.width
+    }
+    /// Returns the current precision.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_precision(&self) -> Option<usize> {
+        self.precision
+    }
+    /// Returns the current precision.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
+        const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32;
+        const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32;
+        match self.flags
+            & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32))
+        {
+            DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper),
+            DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower),
+            0 => None,
+            _ => panic!("Invalid hex debug bits set in flags"),
+        }
+    }
+
+    /// Creates a [`Formatter`] that writes its output to the given [`Write`] trait.
+    ///
+    /// You may alternatively use [`Formatter::new()`].
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
+        Formatter { options: self, buf: write }
+    }
+
+    #[doc(hidden)]
+    #[unstable(
+        feature = "fmt_internals",
+        reason = "internal routines only exposed for testing",
+        issue = "none"
+    )]
+    /// Flags for formatting
+    pub fn flags(&mut self, flags: u32) {
+        self.flags = flags
+    }
+    #[doc(hidden)]
+    #[unstable(
+        feature = "fmt_internals",
+        reason = "internal routines only exposed for testing",
+        issue = "none"
+    )]
+    /// Flags for formatting
+    pub fn get_flags(&self) -> u32 {
+        self.flags
+    }
+}
+
 /// Configuration for formatting.
 ///
 /// A `Formatter` represents various options related to formatting. Users do not
@@ -260,34 +518,28 @@ impl<W: Write + ?Sized> Write for &mut W {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Formatter"]
 pub struct Formatter<'a> {
-    flags: u32,
-    fill: char,
-    align: rt::Alignment,
-    width: Option<usize>,
-    precision: Option<usize>,
+    options: FormattingOptions,
 
     buf: &'a mut (dyn Write + 'a),
 }
 
 impl<'a> Formatter<'a> {
-    /// Creates a new formatter with default settings.
+    /// Creates a new formatter with given [`FormattingOptions`].
     ///
-    /// This can be used as a micro-optimization in cases where a full `Arguments`
-    /// structure (as created by `format_args!`) is not necessary; `Arguments`
-    /// is a little more expensive to use in simple formatting scenarios.
+    /// If `write` is a reference to a formatter, it is recommended to use
+    /// [`Formatter::with_options`] instead as this can borrow the underlying
+    /// `write`, thereby bypassing one layer of indirection.
     ///
-    /// Currently not intended for use outside of the standard library.
-    #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
-    #[doc(hidden)]
-    pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
-        Formatter {
-            flags: 0,
-            fill: ' ',
-            align: rt::Alignment::Unknown,
-            width: None,
-            precision: None,
-            buf,
-        }
+    /// You may alternatively use [`FormattingOptions::create_formatter()`].
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self {
+        Formatter { options, buf: write }
+    }
+
+    /// Creates a new formatter based on this one with given [`FormattingOptions`].
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> {
+        Formatter { options, buf: self.buf }
     }
 }
 
@@ -1165,7 +1417,7 @@ pub trait UpperExp {
 /// [`write!`]: crate::write!
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
-    let mut formatter = Formatter::new(output);
+    let mut formatter = Formatter::new(output, FormattingOptions::new());
     let mut idx = 0;
 
     match args.fmt {
@@ -1214,14 +1466,14 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
 }
 
 unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
-    fmt.fill = arg.fill;
-    fmt.align = arg.align;
-    fmt.flags = arg.flags;
+    fmt.options.fill = arg.fill;
+    fmt.options.align = arg.align.into();
+    fmt.options.flags = arg.flags;
     // SAFETY: arg and args come from the same Arguments,
     // which guarantees the indexes are always within bounds.
     unsafe {
-        fmt.width = getcount(args, &arg.width);
-        fmt.precision = getcount(args, &arg.precision);
+        fmt.options.width = getcount(args, &arg.width);
+        fmt.options.precision = getcount(args, &arg.precision);
     }
 
     // Extract the correct argument
@@ -1280,11 +1532,7 @@ impl<'a> Formatter<'a> {
             buf: wrap(self.buf),
 
             // And preserve these
-            flags: self.flags,
-            fill: self.fill,
-            align: self.align,
-            width: self.width,
-            precision: self.precision,
+            options: self.options,
         }
     }
 
@@ -1365,7 +1613,7 @@ impl<'a> Formatter<'a> {
         }
 
         // The `width` field is more of a `min-width` parameter at this point.
-        match self.width {
+        match self.options.width {
             // If there's no minimum length requirements then we can just
             // write the bytes.
             None => {
@@ -1381,14 +1629,15 @@ impl<'a> Formatter<'a> {
             // The sign and prefix goes before the padding if the fill character
             // is zero
             Some(min) if self.sign_aware_zero_pad() => {
-                let old_fill = crate::mem::replace(&mut self.fill, '0');
-                let old_align = crate::mem::replace(&mut self.align, rt::Alignment::Right);
+                let old_fill = crate::mem::replace(&mut self.options.fill, '0');
+                let old_align =
+                    crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
                 write_prefix(self, sign, prefix)?;
                 let post_padding = self.padding(min - width, Alignment::Right)?;
                 self.buf.write_str(buf)?;
                 post_padding.write(self)?;
-                self.fill = old_fill;
-                self.align = old_align;
+                self.options.fill = old_fill;
+                self.options.align = old_align;
                 Ok(())
             }
             // Otherwise, the sign and prefix goes after the padding
@@ -1433,12 +1682,12 @@ impl<'a> Formatter<'a> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pad(&mut self, s: &str) -> Result {
         // Make sure there's a fast path up front
-        if self.width.is_none() && self.precision.is_none() {
+        if self.options.width.is_none() && self.options.precision.is_none() {
             return self.buf.write_str(s);
         }
         // The `precision` field can be interpreted as a `max-width` for the
         // string being formatted.
-        let s = if let Some(max) = self.precision {
+        let s = if let Some(max) = self.options.precision {
             // If our string is longer that the precision, then we must have
             // truncation. However other flags like `fill`, `width` and `align`
             // must act as always.
@@ -1455,7 +1704,7 @@ impl<'a> Formatter<'a> {
             &s
         };
         // The `width` field is more of a `min-width` parameter at this point.
-        match self.width {
+        match self.options.width {
             // If we're under the maximum length, and there's no minimum length
             // requirements, then we can just emit the string
             None => self.buf.write_str(s),
@@ -1487,12 +1736,7 @@ impl<'a> Formatter<'a> {
         padding: usize,
         default: Alignment,
     ) -> result::Result<PostPadding, Error> {
-        let align = match self.align {
-            rt::Alignment::Unknown => default,
-            rt::Alignment::Left => Alignment::Left,
-            rt::Alignment::Right => Alignment::Right,
-            rt::Alignment::Center => Alignment::Center,
-        };
+        let align = self.align().unwrap_or(default);
 
         let (pre_pad, post_pad) = match align {
             Alignment::Left => (0, padding),
@@ -1501,10 +1745,10 @@ impl<'a> Formatter<'a> {
         };
 
         for _ in 0..pre_pad {
-            self.buf.write_char(self.fill)?;
+            self.buf.write_char(self.options.fill)?;
         }
 
-        Ok(PostPadding::new(self.fill, post_pad))
+        Ok(PostPadding::new(self.options.fill, post_pad))
     }
 
     /// Takes the formatted parts and applies the padding.
@@ -1516,12 +1760,12 @@ impl<'a> Formatter<'a> {
     ///
     /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
     unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        if let Some(mut width) = self.width {
+        if let Some(mut width) = self.options.width {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
             let mut formatted = formatted.clone();
-            let old_fill = self.fill;
-            let old_align = self.align;
+            let old_fill = self.options.fill;
+            let old_align = self.options.align;
             if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = formatted.sign;
@@ -1530,8 +1774,8 @@ impl<'a> Formatter<'a> {
                 // remove the sign from the formatted parts
                 formatted.sign = "";
                 width = width.saturating_sub(sign.len());
-                self.fill = '0';
-                self.align = rt::Alignment::Right;
+                self.options.fill = '0';
+                self.options.align = Some(Alignment::Right);
             }
 
             // remaining parts go through the ordinary padding process.
@@ -1548,8 +1792,8 @@ impl<'a> Formatter<'a> {
                 }
                 post_padding.write(self)
             };
-            self.fill = old_fill;
-            self.align = old_align;
+            self.options.fill = old_fill;
+            self.options.align = old_align;
             ret
         } else {
             // this is the common case and we take a shortcut
@@ -1675,7 +1919,7 @@ impl<'a> Formatter<'a> {
                 or `sign_aware_zero_pad` methods instead"
     )]
     pub fn flags(&self) -> u32 {
-        self.flags
+        self.options.flags
     }
 
     /// Returns the character used as 'fill' whenever there is alignment.
@@ -1708,7 +1952,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn fill(&self) -> char {
-        self.fill
+        self.options.fill
     }
 
     /// Returns a flag indicating what form of alignment was requested.
@@ -1743,12 +1987,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags_align", since = "1.28.0")]
     pub fn align(&self) -> Option<Alignment> {
-        match self.align {
-            rt::Alignment::Left => Some(Alignment::Left),
-            rt::Alignment::Right => Some(Alignment::Right),
-            rt::Alignment::Center => Some(Alignment::Center),
-            rt::Alignment::Unknown => None,
-        }
+        self.options.align
     }
 
     /// Returns the optionally specified integer width that the output should be.
@@ -1778,7 +2017,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> {
-        self.width
+        self.options.width
     }
 
     /// Returns the optionally specified precision for numeric types.
@@ -1809,7 +2048,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> {
-        self.precision
+        self.options.precision
     }
 
     /// Determines if the `+` flag was specified.
@@ -1841,7 +2080,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_plus(&self) -> bool {
-        self.flags & (1 << rt::Flag::SignPlus as u32) != 0
+        self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0
     }
 
     /// Determines if the `-` flag was specified.
@@ -1870,7 +2109,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_minus(&self) -> bool {
-        self.flags & (1 << rt::Flag::SignMinus as u32) != 0
+        self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0
     }
 
     /// Determines if the `#` flag was specified.
@@ -1898,7 +2137,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn alternate(&self) -> bool {
-        self.flags & (1 << rt::Flag::Alternate as u32) != 0
+        self.options.flags & (1 << rt::Flag::Alternate as u32) != 0
     }
 
     /// Determines if the `0` flag was specified.
@@ -1924,17 +2163,17 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_aware_zero_pad(&self) -> bool {
-        self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+        self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
     }
 
     // FIXME: Decide what public API we want for these two flags.
     // https://github.com/rust-lang/rust/issues/48584
     fn debug_lower_hex(&self) -> bool {
-        self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
+        self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
     }
 
     fn debug_upper_hex(&self) -> bool {
-        self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
+        self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
     }
 
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
@@ -2350,6 +2589,18 @@ impl<'a> Formatter<'a> {
     pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> {
         builders::debug_map_new(self)
     }
+
+    /// Returns the sign of this formatter (`+` or `-`).
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn sign(&self) -> Option<Sign> {
+        self.options.get_sign()
+    }
+
+    /// Returns the formatting options this formatter corresponds to.
+    #[unstable(feature = "formatting_options", issue = "118117")]
+    pub const fn options(&self) -> FormattingOptions {
+        self.options
+    }
 }
 
 #[stable(since = "1.2.0", feature = "formatter_write")]
@@ -2502,7 +2753,7 @@ impl Debug for char {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Display for char {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        if f.width.is_none() && f.precision.is_none() {
+        if f.options.width.is_none() && f.options.precision.is_none() {
             f.write_char(*self)
         } else {
             f.pad(self.encode_utf8(&mut [0; 4]))
@@ -2526,26 +2777,26 @@ impl<T: ?Sized> Pointer for *const T {
 ///
 /// [problematic]: https://github.com/rust-lang/rust/issues/95489
 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result {
-    let old_width = f.width;
-    let old_flags = f.flags;
+    let old_width = f.options.width;
+    let old_flags = f.options.flags;
 
     // The alternate flag is already treated by LowerHex as being special-
     // it denotes whether to prefix with 0x. We use it to work out whether
     // or not to zero extend, and then unconditionally set it to get the
     // prefix.
     if f.alternate() {
-        f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
+        f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
 
-        if f.width.is_none() {
-            f.width = Some((usize::BITS / 4) as usize + 2);
+        if f.options.width.is_none() {
+            f.options.width = Some((usize::BITS / 4) as usize + 2);
         }
     }
-    f.flags |= 1 << (rt::Flag::Alternate as u32);
+    f.options.flags |= 1 << (rt::Flag::Alternate as u32);
 
     let ret = LowerHex::fmt(&ptr_addr, f);
 
-    f.width = old_width;
-    f.flags = old_flags;
+    f.options.width = old_width;
+    f.options.flags = old_flags;
 
     ret
 }
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 2cf2ea58fd4..c3c7288e389 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -492,131 +492,150 @@ impl Extend<()> for () {
     fn extend_one(&mut self, _item: ()) {}
 }
 
-#[stable(feature = "extend_for_tuple", since = "1.56.0")]
-impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
-where
-    ExtendA: Extend<A>,
-    ExtendB: Extend<B>,
-{
-    /// Allows to `extend` a tuple of collections that also implement `Extend`.
-    ///
-    /// See also: [`Iterator::unzip`]
-    ///
-    /// # Examples
-    /// ```
-    /// let mut tuple = (vec![0], vec![1]);
-    /// tuple.extend([(2, 3), (4, 5), (6, 7)]);
-    /// assert_eq!(tuple.0, [0, 2, 4, 6]);
-    /// assert_eq!(tuple.1, [1, 3, 5, 7]);
-    ///
-    /// // also allows for arbitrarily nested tuples as elements
-    /// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
-    /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
-    ///
-    /// let (a, (b, c)) = nested_tuple;
-    /// assert_eq!(a, [1, 4, 7]);
-    /// assert_eq!(b, [2, 5, 8]);
-    /// assert_eq!(c, [3, 6, 9]);
-    /// ```
-    fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
-        let (a, b) = self;
-        let iter = into_iter.into_iter();
-        SpecTupleExtend::extend(iter, a, b);
-    }
+macro_rules! spec_tuple_impl {
+    ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
+        spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
+    };
+    ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident,  $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {
 
-    fn extend_one(&mut self, item: (A, B)) {
-        self.0.extend_one(item.0);
-        self.1.extend_one(item.1);
-    }
+        spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
+        spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
+    };
+    ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
+        #[$meta]
+        $(#[$doctext])?
+        #[stable(feature = "extend_for_tuple", since = "1.56.0")]
+        impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*)
+        where
+            $($extend_ty_names: Extend<$ty_names>,)*
+        {
+            /// Allows to `extend` a tuple of collections that also implement `Extend`.
+            ///
+            /// See also: [`Iterator::unzip`]
+            ///
+            /// # Examples
+            /// ```
+            /// // Example given for a 2-tuple, but 1- through 12-tuples are supported
+            /// let mut tuple = (vec![0], vec![1]);
+            /// tuple.extend([(2, 3), (4, 5), (6, 7)]);
+            /// assert_eq!(tuple.0, [0, 2, 4, 6]);
+            /// assert_eq!(tuple.1, [1, 3, 5, 7]);
+            ///
+            /// // also allows for arbitrarily nested tuples as elements
+            /// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
+            /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
+            ///
+            /// let (a, (b, c)) = nested_tuple;
+            /// assert_eq!(a, [1, 4, 7]);
+            /// assert_eq!(b, [2, 5, 8]);
+            /// assert_eq!(c, [3, 6, 9]);
+            /// ```
+            fn extend<T: IntoIterator<Item = ($($ty_names,)*)>>(&mut self, into_iter: T) {
+                let ($($var_names,)*) = self;
+                let iter = into_iter.into_iter();
+                $trait_name::extend(iter, $($var_names,)*);
+            }
 
-    fn extend_reserve(&mut self, additional: usize) {
-        self.0.extend_reserve(additional);
-        self.1.extend_reserve(additional);
-    }
+            fn extend_one(&mut self, item: ($($ty_names,)*)) {
+                $(self.$cnts.extend_one(item.$cnts);)*
+            }
 
-    unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {
-        // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
-        unsafe {
-            self.0.extend_one_unchecked(item.0);
-            self.1.extend_one_unchecked(item.1);
-        }
-    }
-}
+            fn extend_reserve(&mut self, additional: usize) {
+                $(self.$cnts.extend_reserve(additional);)*
+            }
 
-fn default_extend_tuple<A, B, ExtendA, ExtendB>(
-    iter: impl Iterator<Item = (A, B)>,
-    a: &mut ExtendA,
-    b: &mut ExtendB,
-) where
-    ExtendA: Extend<A>,
-    ExtendB: Extend<B>,
-{
-    fn extend<'a, A, B>(
-        a: &'a mut impl Extend<A>,
-        b: &'a mut impl Extend<B>,
-    ) -> impl FnMut((), (A, B)) + 'a {
-        move |(), (t, u)| {
-            a.extend_one(t);
-            b.extend_one(u);
+            unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) {
+                // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
+                unsafe {
+                     $(self.$cnts.extend_one_unchecked(item.$cnts);)*
+                }
+            }
         }
-    }
 
-    let (lower_bound, _) = iter.size_hint();
-    if lower_bound > 0 {
-        a.extend_reserve(lower_bound);
-        b.extend_reserve(lower_bound);
-    }
+        trait $trait_name<$($ty_names),*> {
+            fn extend(self, $($var_names: &mut $ty_names,)*);
+        }
 
-    iter.fold((), extend(a, b));
-}
+        fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>(
+            iter: impl Iterator<Item = ($($ty_names,)*)>,
+            $($var_names: &mut $extend_ty_names,)*
+        ) where
+            $($extend_ty_names: Extend<$ty_names>,)*
+        {
+            fn extend<'a, $($ty_names,)*>(
+                $($var_names: &'a mut impl Extend<$ty_names>,)*
+            ) -> impl FnMut((), ($($ty_names,)*)) + 'a {
+                #[allow(non_snake_case)]
+                move |(), ($($extend_ty_names,)*)| {
+                    $($var_names.extend_one($extend_ty_names);)*
+                }
+            }
 
-trait SpecTupleExtend<A, B> {
-    fn extend(self, a: &mut A, b: &mut B);
-}
+            let (lower_bound, _) = iter.size_hint();
+            if lower_bound > 0 {
+                $($var_names.extend_reserve(lower_bound);)*
+            }
 
-impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
-where
-    ExtendA: Extend<A>,
-    ExtendB: Extend<B>,
-    Iter: Iterator<Item = (A, B)>,
-{
-    default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
-        default_extend_tuple(self, a, b);
-    }
-}
+            iter.fold((), extend($($var_names,)*));
+        }
 
-impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
-where
-    ExtendA: Extend<A>,
-    ExtendB: Extend<B>,
-    Iter: TrustedLen<Item = (A, B)>,
-{
-    fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
-        fn extend<'a, A, B>(
-            a: &'a mut impl Extend<A>,
-            b: &'a mut impl Extend<B>,
-        ) -> impl FnMut((), (A, B)) + 'a {
-            // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
-            // so its `size_hint` is exact.
-            move |(), (t, u)| unsafe {
-                a.extend_one_unchecked(t);
-                b.extend_one_unchecked(u);
+        impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
+            where
+            $($extend_ty_names: Extend<$ty_names>,)*
+            Iter: Iterator<Item = ($($ty_names,)*)>,
+        {
+            default fn extend(self, $($var_names: &mut $extend_ty_names),*) {
+                $default_fn_name(self, $($var_names),*);
             }
         }
 
-        let (lower_bound, upper_bound) = self.size_hint();
+        impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
+            where
+            $($extend_ty_names: Extend<$ty_names>,)*
+            Iter: TrustedLen<Item = ($($ty_names,)*)>,
+        {
+            fn extend(self, $($var_names: &mut $extend_ty_names,)*) {
+                fn extend<'a, $($ty_names,)*>(
+                    $($var_names: &'a mut impl Extend<$ty_names>,)*
+                ) -> impl FnMut((), ($($ty_names,)*)) + 'a {
+                #[allow(non_snake_case)]
+                // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
+                // so its `size_hint` is exact.
+                move |(), ($($extend_ty_names,)*)| unsafe {
+                    $($var_names.extend_one_unchecked($extend_ty_names);)*
+                }
+            }
 
-        if upper_bound.is_none() {
-            // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
-            default_extend_tuple(self, a, b);
-            return;
-        }
+            let (lower_bound, upper_bound) = self.size_hint();
 
-        if lower_bound > 0 {
-            a.extend_reserve(lower_bound);
-            b.extend_reserve(lower_bound);
-        }
+            if upper_bound.is_none() {
+                // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
+                $default_fn_name(self, $($var_names,)*);
+                return;
+            }
 
-        self.fold((), extend(a, b));
+            if lower_bound > 0 {
+                $($var_names.extend_reserve(lower_bound);)*
+            }
+
+            self.fold((), extend($($var_names,)*));
+        }
     }
+
+    };
 }
+
+spec_tuple_impl!(
+    (L, l, EL, TraitL, default_extend_tuple_l, 11),
+    (K, k, EK, TraitK, default_extend_tuple_k, 10),
+    (J, j, EJ, TraitJ, default_extend_tuple_j, 9),
+    (I, i, EI, TraitI, default_extend_tuple_i, 8),
+    (H, h, EH, TraitH, default_extend_tuple_h, 7),
+    (G, g, EG, TraitG, default_extend_tuple_g, 6),
+    (F, f, EF, TraitF, default_extend_tuple_f, 5),
+    (E, e, EE, TraitE, default_extend_tuple_e, 4),
+    (D, d, ED, TraitD, default_extend_tuple_d, 3),
+    (C, c, EC, TraitC, default_extend_tuple_c, 2),
+    (B, b, EB, TraitB, default_extend_tuple_b, 1),
+    (A, a, EA, TraitA, default_extend_tuple_a, 0),
+);
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 41e9c593ebd..6762ed54e5c 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -60,7 +60,8 @@ impl RawWaker {
         RawWaker { data, vtable }
     }
 
-    #[unstable(feature = "noop_waker", issue = "98286")]
+    #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")]
     const NOOP: RawWaker = {
         const VTABLE: RawWakerVTable = RawWakerVTable::new(
             // Cloning just returns a new no-op raw waker
@@ -283,7 +284,6 @@ impl fmt::Debug for Context<'_> {
 /// # Examples
 /// ```
 /// #![feature(local_waker)]
-/// #![feature(noop_waker)]
 /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll};
 /// use std::future::Future;
 ///
@@ -555,8 +555,6 @@ impl Waker {
     /// # Examples
     ///
     /// ```
-    /// #![feature(noop_waker)]
-    ///
     /// use std::future::Future;
     /// use std::task;
     ///
@@ -567,7 +565,8 @@ impl Waker {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "noop_waker", issue = "98286")]
+    #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")]
     pub const fn noop() -> &'static Waker {
         const WAKER: &Waker = &Waker { waker: RawWaker::NOOP };
         WAKER
@@ -850,8 +849,6 @@ impl LocalWaker {
     ///
     /// ```
     /// #![feature(local_waker)]
-    /// #![feature(noop_waker)]
-    ///
     /// use std::future::Future;
     /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll};
     ///
@@ -864,7 +861,7 @@ impl LocalWaker {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "noop_waker", issue = "98286")]
+    #[unstable(feature = "local_waker", issue = "118959")]
     pub const fn noop() -> &'static LocalWaker {
         const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP };
         WAKER
diff --git a/library/core/src/unicode/printable.py b/library/core/src/unicode/printable.py
index 4d39ace066c..260fa9f9e6a 100755
--- a/library/core/src/unicode/printable.py
+++ b/library/core/src/unicode/printable.py
@@ -9,7 +9,8 @@ import csv
 import os
 import subprocess
 
-NUM_CODEPOINTS=0x110000
+NUM_CODEPOINTS = 0x110000
+
 
 def to_ranges(iter):
     current = None
@@ -23,11 +24,15 @@ def to_ranges(iter):
     if current is not None:
         yield tuple(current)
 
+
 def get_escaped(codepoints):
     for c in codepoints:
-        if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '):
+        if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(
+            " "
+        ):
             yield c.value
 
+
 def get_file(f):
     try:
         return open(os.path.basename(f))
@@ -35,7 +40,9 @@ def get_file(f):
         subprocess.run(["curl", "-O", f], check=True)
         return open(os.path.basename(f))
 
-Codepoint = namedtuple('Codepoint', 'value class_')
+
+Codepoint = namedtuple("Codepoint", "value class_")
+
 
 def get_codepoints(f):
     r = csv.reader(f, delimiter=";")
@@ -66,13 +73,14 @@ def get_codepoints(f):
     for c in range(prev_codepoint + 1, NUM_CODEPOINTS):
         yield Codepoint(c, None)
 
+
 def compress_singletons(singletons):
-    uppers = [] # (upper, # items in lowers)
+    uppers = []  # (upper, # items in lowers)
     lowers = []
 
     for i in singletons:
         upper = i >> 8
-        lower = i & 0xff
+        lower = i & 0xFF
         if len(uppers) == 0 or uppers[-1][0] != upper:
             uppers.append((upper, 1))
         else:
@@ -82,10 +90,11 @@ def compress_singletons(singletons):
 
     return uppers, lowers
 
+
 def compress_normal(normal):
     # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f
     # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff
-    compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)]
+    compressed = []  # [truelen, (truelenaux), falselen, (falselenaux)]
 
     prev_start = 0
     for start, count in normal:
@@ -95,21 +104,22 @@ def compress_normal(normal):
 
         assert truelen < 0x8000 and falselen < 0x8000
         entry = []
-        if truelen > 0x7f:
+        if truelen > 0x7F:
             entry.append(0x80 | (truelen >> 8))
-            entry.append(truelen & 0xff)
+            entry.append(truelen & 0xFF)
         else:
-            entry.append(truelen & 0x7f)
-        if falselen > 0x7f:
+            entry.append(truelen & 0x7F)
+        if falselen > 0x7F:
             entry.append(0x80 | (falselen >> 8))
-            entry.append(falselen & 0xff)
+            entry.append(falselen & 0xFF)
         else:
-            entry.append(falselen & 0x7f)
+            entry.append(falselen & 0x7F)
 
         compressed.append(entry)
 
     return compressed
 
+
 def print_singletons(uppers, lowers, uppersname, lowersname):
     print("#[rustfmt::skip]")
     print("const {}: &[(u8, u8)] = &[".format(uppersname))
@@ -119,9 +129,12 @@ def print_singletons(uppers, lowers, uppersname, lowersname):
     print("#[rustfmt::skip]")
     print("const {}: &[u8] = &[".format(lowersname))
     for i in range(0, len(lowers), 8):
-        print("    {}".format(" ".join("{:#04x},".format(x) for x in lowers[i:i+8])))
+        print(
+            "    {}".format(" ".join("{:#04x},".format(x) for x in lowers[i : i + 8]))
+        )
     print("];")
 
+
 def print_normal(normal, normalname):
     print("#[rustfmt::skip]")
     print("const {}: &[u8] = &[".format(normalname))
@@ -129,12 +142,13 @@ def print_normal(normal, normalname):
         print("    {}".format(" ".join("{:#04x},".format(i) for i in v)))
     print("];")
 
+
 def main():
     file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
 
     codepoints = get_codepoints(file)
 
-    CUTOFF=0x10000
+    CUTOFF = 0x10000
     singletons0 = []
     singletons1 = []
     normal0 = []
@@ -234,10 +248,11 @@ pub(crate) fn is_printable(x: char) -> bool {
 }\
 """)
     print()
-    print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L')
-    print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L')
-    print_normal(normal0, 'NORMAL0')
-    print_normal(normal1, 'NORMAL1')
+    print_singletons(singletons0u, singletons0l, "SINGLETONS0U", "SINGLETONS0L")
+    print_singletons(singletons1u, singletons1l, "SINGLETONS1U", "SINGLETONS1L")
+    print_normal(normal0, "NORMAL0")
+    print_normal(normal1, "NORMAL1")
+
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs
index f7512abae38..2c93a9bc80d 100644
--- a/library/core/tests/fmt/mod.rs
+++ b/library/core/tests/fmt/mod.rs
@@ -50,3 +50,27 @@ fn test_maybe_uninit_short() {
     let x = core::mem::MaybeUninit::new(0u32);
     assert_eq!(format!("{x:?}"), "MaybeUninit<u32>");
 }
+
+#[test]
+fn formatting_options_flags() {
+    use core::fmt::*;
+    for sign in [None, Some(Sign::Plus), Some(Sign::Minus)] {
+        for alternate in [true, false] {
+            for sign_aware_zero_pad in [true, false] {
+                for debug_as_hex in [None, Some(DebugAsHex::Lower), Some(DebugAsHex::Upper)] {
+                    let mut formatting_options = FormattingOptions::new();
+                    formatting_options
+                        .sign(sign)
+                        .sign_aware_zero_pad(sign_aware_zero_pad)
+                        .alternate(alternate)
+                        .debug_as_hex(debug_as_hex);
+
+                    assert_eq!(formatting_options.get_sign(), sign);
+                    assert_eq!(formatting_options.get_alternate(), alternate);
+                    assert_eq!(formatting_options.get_sign_aware_zero_pad(), sign_aware_zero_pad);
+                    assert_eq!(formatting_options.get_debug_as_hex(), debug_as_hex);
+                }
+            }
+        }
+    }
+}
diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs
index 93ef9c0812b..76f1e3319d4 100644
--- a/library/core/tests/iter/traits/iterator.rs
+++ b/library/core/tests/iter/traits/iterator.rs
@@ -617,6 +617,19 @@ fn test_next_chunk() {
     assert_eq!(it.next_chunk::<0>().unwrap(), []);
 }
 
+#[test]
+fn test_collect_into_tuples() {
+    let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)];
+    let b = vec![1, 4, 7];
+    let c = vec![2, 5, 8];
+    let d = vec![3, 6, 9];
+    let mut e = (Vec::new(), Vec::new(), Vec::new());
+    a.iter().cloned().collect_into(&mut e);
+    assert!(e.0 == b);
+    assert!(e.1 == c);
+    assert!(e.2 == d);
+}
+
 // just tests by whether or not this compiles
 fn _empty_impl_all_auto_traits<T>() {
     use std::panic::{RefUnwindSafe, UnwindSafe};
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index e0b1c21e1ec..a4a794691fe 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -31,6 +31,7 @@
 #![feature(float_minimum_maximum)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
+#![feature(formatting_options)]
 #![feature(freeze)]
 #![feature(future_join)]
 #![feature(generic_assert_internals)]
@@ -61,7 +62,6 @@
 #![feature(maybe_uninit_write_slice)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(noop_waker)]
 #![feature(num_midpoint_signed)]
 #![feature(numfmt)]
 #![feature(pattern)]
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 03f38e220a5..476c403c21f 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -338,9 +338,9 @@ pub enum ErrorKind {
     /// example, on Unix, a named pipe opened with `File::open`.
     #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
     NotSeekable,
-    /// Filesystem quota was exceeded.
-    #[unstable(feature = "io_error_more", issue = "86442")]
-    FilesystemQuotaExceeded,
+    /// Filesystem quota or some other kind of quota was exceeded.
+    #[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")]
+    QuotaExceeded,
     /// File larger than allowed or supported.
     ///
     /// This might arise from a hard limit of the underlying filesystem or file access API, or from
@@ -364,7 +364,7 @@ pub enum ErrorKind {
     #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
     Deadlock,
     /// Cross-device or cross-filesystem (hard) link or rename.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")]
     CrossesDevices,
     /// Too many (hard) links to the same filesystem object.
     ///
@@ -446,8 +446,8 @@ pub enum ErrorKind {
 impl ErrorKind {
     pub(crate) fn as_str(&self) -> &'static str {
         use ErrorKind::*;
-        // tidy-alphabetical-start
         match *self {
+            // tidy-alphabetical-start
             AddrInUse => "address in use",
             AddrNotAvailable => "address not available",
             AlreadyExists => "entity already exists",
@@ -460,12 +460,11 @@ impl ErrorKind {
             Deadlock => "deadlock",
             DirectoryNotEmpty => "directory not empty",
             ExecutableFileBusy => "executable file busy",
-            FileTooLarge => "file too large",
             FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
-            FilesystemQuotaExceeded => "filesystem quota exceeded",
+            FileTooLarge => "file too large",
             HostUnreachable => "host unreachable",
-            Interrupted => "operation interrupted",
             InProgress => "in progress",
+            Interrupted => "operation interrupted",
             InvalidData => "invalid data",
             InvalidFilename => "invalid filename",
             InvalidInput => "invalid input parameter",
@@ -479,6 +478,7 @@ impl ErrorKind {
             Other => "other error",
             OutOfMemory => "out of memory",
             PermissionDenied => "permission denied",
+            QuotaExceeded => "quota exceeded",
             ReadOnlyFilesystem => "read-only filesystem or storage medium",
             ResourceBusy => "resource busy",
             StaleNetworkFileHandle => "stale network file handle",
@@ -490,8 +490,8 @@ impl ErrorKind {
             Unsupported => "unsupported",
             WouldBlock => "operation would block",
             WriteZero => "write zero",
+            // tidy-alphabetical-end
         }
-        // tidy-alphabetical-end
     }
 }
 
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index a839a2fbac1..f958a938646 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -335,7 +335,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
         WriteZero,
         StorageFull,
         NotSeekable,
-        FilesystemQuotaExceeded,
+        QuotaExceeded,
         FileTooLarge,
         ResourceBusy,
         ExecutableFileBusy,
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 6be27b283b2..49a03220039 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -292,6 +292,7 @@
 #![feature(dropck_eyepatch)]
 #![feature(f128)]
 #![feature(f16)]
+#![feature(formatting_options)]
 #![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
 #![feature(lang_items)]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 97f800dddaa..dca5ccca0c4 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -623,7 +623,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
             // Lazily, the first time this gets called, run the actual string formatting.
             self.string.get_or_insert_with(|| {
                 let mut s = String::new();
-                let mut fmt = fmt::Formatter::new(&mut s);
+                let mut fmt = fmt::Formatter::new(&mut s, fmt::FormattingOptions::new());
                 let _err = fmt::Display::fmt(&inner, &mut fmt);
                 s
             })
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 2bf2e2ceb31..a9900f55b19 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -71,7 +71,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::ECONNREFUSED => ConnectionRefused,
         libc::ECONNRESET => ConnectionReset,
         libc::EDEADLK => Deadlock,
-        libc::EDQUOT => FilesystemQuotaExceeded,
+        libc::EDQUOT => QuotaExceeded,
         libc::EEXIST => AlreadyExists,
         libc::EFBIG => FileTooLarge,
         libc::EHOSTUNREACH => HostUnreachable,
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 8eaa50d7f81..3cc1cae8d00 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -254,7 +254,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::ECONNREFUSED => ConnectionRefused,
         libc::ECONNRESET => ConnectionReset,
         libc::EDEADLK => Deadlock,
-        libc::EDQUOT => FilesystemQuotaExceeded,
+        libc::EDQUOT => QuotaExceeded,
         libc::EEXIST => AlreadyExists,
         libc::EFBIG => FileTooLarge,
         libc::EHOSTUNREACH => HostUnreachable,
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index d66ff15e10b..88e6def7a75 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -113,7 +113,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem,
         c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull,
         c::ERROR_SEEK_ON_DEVICE => return NotSeekable,
-        c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded,
+        c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded,
         c::ERROR_FILE_TOO_LARGE => return FileTooLarge,
         c::ERROR_BUSY => return ResourceBusy,
         c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
@@ -138,7 +138,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         c::WSAEHOSTUNREACH => HostUnreachable,
         c::WSAENETDOWN => NetworkDown,
         c::WSAENETUNREACH => NetworkUnreachable,
-        c::WSAEDQUOT => FilesystemQuotaExceeded,
+        c::WSAEDQUOT => QuotaExceeded,
 
         _ => Uncategorized,
     }
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9ef9ccec193..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,14 +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"),
-                "-Zroot-dir="+self.rust_root]
+            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")
@@ -1058,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)
 
@@ -1144,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
@@ -1196,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
@@ -1207,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
@@ -1222,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/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 161157acffe..30fdea7e19e 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1070,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_sysroot.join("bin");
-                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");
@@ -2624,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");
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/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-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 2ea37c168dd..288b133f0da 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -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
@@ -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
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/doc/book b/src/doc/book
-Subproject 614c19cb4025636eb2ba68ebb3d44e3bd3a5e6e
+Subproject 9900d976bbfecf4e8124da54351a9ad85ee3c7f
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/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_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_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/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/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5e3d06a4ae7..90c49270566 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -32,6 +32,8 @@ use std::iter::Peekable;
 use std::ops::{ControlFlow, Range};
 use std::path::PathBuf;
 use std::str::{self, CharIndices};
+use std::sync::atomic::AtomicUsize;
+use std::sync::{Arc, Weak};
 
 use pulldown_cmark::{
     BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
@@ -1301,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,
@@ -1313,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,7 +1936,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
     map: FxHashMap<String, usize>,
-    existing_footnotes: usize,
+    existing_footnotes: Arc<AtomicUsize>,
 }
 
 fn is_default_id(id: &str) -> bool {
@@ -1942,7 +1996,7 @@ fn is_default_id(id: &str) -> bool {
 
 impl IdMap {
     pub fn new() -> Self {
-        IdMap { map: FxHashMap::default(), 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 {
@@ -1970,15 +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, &mut existing_footnotes);
-        self.existing_footnotes = existing_footnotes;
+        closure(self, existing_footnotes)
     }
 
     pub(crate) fn clear(&mut self) {
         self.map.clear();
-        self.existing_footnotes = 0;
+        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/mod.rs b/src/librustdoc/html/render/mod.rs
index f4367257572..e013829e5e0 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1904,7 +1904,6 @@ fn render_impl(
         }
     }
 
-    let trait_is_none = trait_.is_none();
     // If we've implemented a trait, then also emit documentation for all
     // default items which weren't overridden in the implementation block.
     // We don't emit documentation for default items if they appear in the
@@ -1936,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,
@@ -1944,33 +1960,23 @@ 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 trait_is_none && impl_.items.is_empty() {
+        if before_dox.is_some() {
+            if trait_.is_none() && impl_.items.is_empty() {
                 w.write_str(
                     "<div class=\"item-info\">\
                          <div class=\"stab empty-impl\">This impl block contains no items.</div>\
                      </div>",
                 );
             }
-            write!(
-                w,
-                "<div class=\"docblock\">{}</div>",
-                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,
-                }
-                .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\">");
@@ -2031,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));
@@ -2082,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>");
 }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 90aa5904daf..27496381b2c 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -2210,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;
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 05f54fdc34310f458033af8a63ce1d699fae8bf
+Subproject 20a443231846b81c7b909691ec3f15eb173f2b1
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/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/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 8469744bbc4..9fb81453ec6 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -532,8 +532,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/machine.rs b/src/tools/miri/src/machine.rs
index 814dc6d2b01..888465c5262 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,8 @@ 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/io_error.rs b/src/tools/miri/src/shims/io_error.rs
index 0cbb4850b7f..634dbd9f953 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),
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index e7a4251242e..4082b8eed45 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -3,8 +3,11 @@ use std::ops::Deref;
 
 use libffi::high::call as ffi;
 use libffi::low::CodePtr;
-use rustc_abi::{BackendRepr, HasDataLayout};
-use rustc_middle::ty::{self as ty, IntTy, UintTy};
+use rustc_abi::{BackendRepr, HasDataLayout, Size};
+use rustc_middle::{
+    mir::interpret::Pointer,
+    ty::{self as ty, IntTy, UintTy},
+};
 use rustc_span::Symbol;
 
 use crate::*;
@@ -75,6 +78,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,8 +160,26 @@ 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
@@ -220,7 +246,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 +264,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/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..4045ef3cee5
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs
@@ -0,0 +1,208 @@
+// 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/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs
index 423ef7a5cf7..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, async_trait_bounds)]
+#![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 264da5a9518..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_trait_bounds)]
+#![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/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/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/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/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/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/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/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 400eb7c5e0d..024b8f9becb 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -709,31 +709,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"
@@ -1010,7 +1000,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 +1018,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 +1044,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]]
@@ -1144,8 +1146,7 @@ dependencies = [
  "mdbook",
  "mdbook-i18n-helpers",
  "mdbook-spec",
- "mdbook-trpl-listing",
- "mdbook-trpl-note",
+ "mdbook-trpl",
 ]
 
 [[package]]
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/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 afa0b9a6760..7d3287aaeb9 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -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/issues.txt b/src/tools/tidy/src/issues.txt
index ac82a17e145..3a021e189f3 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
@@ -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/tests/codegen-units/item-collection/static-init.rs b/tests/codegen-units/item-collection/static-init.rs
index 1406fba2b98..44b80ef73a4 100644
--- a/tests/codegen-units/item-collection/static-init.rs
+++ b/tests/codegen-units/item-collection/static-init.rs
@@ -1,4 +1,4 @@
-//@ compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on
+//@ compile-flags:-Zprint-mono-items=eager
 
 #![feature(start)]
 
@@ -6,7 +6,7 @@ pub static FN: fn() = foo::<i32>;
 
 pub fn foo<T>() {}
 
-//~ MONO_ITEM fn foo::<T>
+//~ MONO_ITEM fn foo::<i32>
 //~ MONO_ITEM static FN
 
 //~ MONO_ITEM fn start
diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs
index b0a43d28e40..fd73786a402 100644
--- a/tests/codegen-units/item-collection/trait-method-default-impl.rs
+++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs
@@ -1,4 +1,4 @@
-//@ compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on -Zinline-mir=no
+//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no
 
 #![deny(dead_code)]
 #![feature(start)]
@@ -29,7 +29,7 @@ impl SomeGenericTrait<u64> for i32 {
 
     // For the non-generic foo(), we should generate a codegen-item even if it
     // is not called anywhere
-    //~ MONO_ITEM fn <i32 as SomeGenericTrait<T1>>::foo
+    //~ MONO_ITEM fn <i32 as SomeGenericTrait<u64>>::foo
 }
 
 // Non-generic impl of generic trait
diff --git a/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs b/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs
deleted file mode 100644
index d6cbd282ec1..00000000000
--- a/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ compile-flags: -Zpolymorphize=on
-
-#[inline(never)]
-pub fn foo<T>() {}
diff --git a/tests/codegen-units/polymorphization/poly-foreign.rs b/tests/codegen-units/polymorphization/poly-foreign.rs
deleted file mode 100644
index 05dbac46d36..00000000000
--- a/tests/codegen-units/polymorphization/poly-foreign.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ aux-build:poly-dep.rs
-//@ compile-flags: --crate-type=lib -Zprint-mono-items=eager -Zpolymorphize=on
-
-extern crate poly_dep;
-
-pub static FN1: fn() = poly_dep::foo::<i32>;
-pub static FN2: fn() = poly_dep::foo::<u32>;
-
-//~ MONO_ITEM static FN1
-//~ MONO_ITEM static FN2
-//~ MONO_ITEM fn poly_dep::foo::<T>
diff --git a/tests/codegen-units/polymorphization/unused_type_parameters.rs b/tests/codegen-units/polymorphization/unused_type_parameters.rs
deleted file mode 100644
index 438305f112f..00000000000
--- a/tests/codegen-units/polymorphization/unused_type_parameters.rs
+++ /dev/null
@@ -1,315 +0,0 @@
-//@ compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1
-
-#![crate_type = "rlib"]
-
-// This test checks that the polymorphization analysis correctly reduces the
-// generated mono items.
-
-mod functions {
-    // Function doesn't have any type parameters to be unused.
-    pub fn no_parameters() {}
-
-    //~ MONO_ITEM fn functions::no_parameters
-
-    // Function has an unused type parameter.
-    pub fn unused<T>() {}
-
-    //~ MONO_ITEM fn functions::unused::<T>
-
-    // Function uses type parameter in value of a binding.
-    pub fn used_binding_value<T: Default>() {
-        let _: T = Default::default();
-    }
-
-    //~ MONO_ITEM fn functions::used_binding_value::<u32>
-    //~ MONO_ITEM fn functions::used_binding_value::<u64>
-
-    // Function uses type parameter in type of a binding.
-    pub fn used_binding_type<T>() {
-        let _: Option<T> = None;
-    }
-
-    //~ MONO_ITEM fn functions::used_binding_type::<u32>
-    //~ MONO_ITEM fn functions::used_binding_type::<u64>
-
-    // Function uses type parameter in argument.
-    pub fn used_argument<T>(_: T) {}
-
-    //~ MONO_ITEM fn functions::used_argument::<u32>
-    //~ MONO_ITEM fn functions::used_argument::<u64>
-    //
-    // Function uses type parameter in substitutions to another function.
-    pub fn used_substs<T>() {
-        unused::<T>()
-    }
-
-    //~ MONO_ITEM fn functions::used_substs::<u32>
-    //~ MONO_ITEM fn functions::used_substs::<u64>
-}
-
-mod closures {
-    // Function doesn't have any type parameters to be unused.
-    pub fn no_parameters() {
-        let _ = || {};
-    }
-
-    //~ MONO_ITEM fn closures::no_parameters
-
-    // Function has an unused type parameter in parent and closure.
-    pub fn unused<T>() -> u32 {
-        let add_one = |x: u32| x + 1;
-        add_one(3)
-    }
-
-    //~ MONO_ITEM fn closures::unused::<T>::{closure#0}
-    //~ MONO_ITEM fn closures::unused::<T>
-
-    // Function has an unused type parameter in closure, but not in parent.
-    pub fn used_parent<T: Default>() -> u32 {
-        let _: T = Default::default();
-        let add_one = |x: u32| x + 1;
-        add_one(3)
-    }
-
-    //~ MONO_ITEM fn closures::used_parent::<T>::{closure#0}
-    //~ MONO_ITEM fn closures::used_parent::<u32>
-    //~ MONO_ITEM fn closures::used_parent::<u64>
-
-    // Function uses type parameter in value of a binding in closure.
-    pub fn used_binding_value<T: Default>() -> T {
-        let x = || {
-            let y: T = Default::default();
-            y
-        };
-
-        x()
-    }
-
-    //~ MONO_ITEM fn closures::used_binding_value::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_binding_value::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_binding_value::<u32>
-    //~ MONO_ITEM fn closures::used_binding_value::<u64>
-
-    // Function uses type parameter in type of a binding in closure.
-    pub fn used_binding_type<T>() -> Option<T> {
-        let x = || {
-            let y: Option<T> = None;
-            y
-        };
-
-        x()
-    }
-
-    //~ MONO_ITEM fn closures::used_binding_type::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_binding_type::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_binding_type::<u32>
-    //~ MONO_ITEM fn closures::used_binding_type::<u64>
-
-    // Function and closure uses type parameter in argument.
-    pub fn used_argument<T>(t: T) -> u32 {
-        let x = |_: T| 3;
-        x(t)
-    }
-
-    //~ MONO_ITEM fn closures::used_argument::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_argument::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_argument::<u32>
-    //~ MONO_ITEM fn closures::used_argument::<u64>
-
-    // Closure uses type parameter in argument.
-    pub fn used_argument_closure<T: Default>() -> u32 {
-        let t: T = Default::default();
-        let x = |_: T| 3;
-        x(t)
-    }
-
-    //~ MONO_ITEM fn closures::used_argument_closure::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_argument_closure::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_argument_closure::<u32>
-    //~ MONO_ITEM fn closures::used_argument_closure::<u64>
-
-    // Closure uses type parameter as upvar.
-    pub fn used_upvar<T: Default>() -> T {
-        let x: T = Default::default();
-        let y = || x;
-        y()
-    }
-
-    //~ MONO_ITEM fn closures::used_upvar::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_upvar::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_upvar::<u32>
-    //~ MONO_ITEM fn closures::used_upvar::<u64>
-
-    // Closure uses type parameter in substitutions to another function.
-    pub fn used_substs<T>() {
-        let x = || super::functions::unused::<T>();
-        x()
-    }
-
-    //~ MONO_ITEM fn closures::used_substs::<u32>::{closure#0}
-    //~ MONO_ITEM fn closures::used_substs::<u64>::{closure#0}
-    //~ MONO_ITEM fn closures::used_substs::<u32>
-    //~ MONO_ITEM fn closures::used_substs::<u64>
-}
-
-mod methods {
-    pub struct Foo<F>(F);
-
-    impl<F: Default> Foo<F> {
-        // Function has an unused type parameter from impl.
-        pub fn unused_impl() {}
-
-        //~ MONO_ITEM fn methods::Foo::<F>::unused_impl
-
-        // Function has an unused type parameter from impl and fn.
-        pub fn unused_both<G: Default>() {}
-
-        //~ MONO_ITEM fn methods::Foo::<F>::unused_both::<G>
-
-        // Function uses type parameter from impl.
-        pub fn used_impl() {
-            let _: F = Default::default();
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::used_impl
-        //~ MONO_ITEM fn methods::Foo::<u64>::used_impl
-
-        // Function uses type parameter from impl.
-        pub fn used_fn<G: Default>() {
-            let _: G = Default::default();
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u32>
-        //~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u64>
-
-        // Function uses type parameter from impl.
-        pub fn used_both<G: Default>() {
-            let _: F = Default::default();
-            let _: G = Default::default();
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::used_both::<u32>
-        //~ MONO_ITEM fn methods::Foo::<u64>::used_both::<u64>
-
-        // Function uses type parameter in substitutions to another function.
-        pub fn used_substs() {
-            super::functions::unused::<F>()
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::used_substs
-        //~ MONO_ITEM fn methods::Foo::<u64>::used_substs
-
-        // Function has an unused type parameter from impl and fn.
-        pub fn closure_unused_all<G: Default>() -> u32 {
-            let add_one = |x: u32| x + 1;
-            add_one(3)
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G>
-
-        // Function uses type parameter from impl and fn in closure.
-        pub fn closure_used_both<G: Default>() -> u32 {
-            let add_one = |x: u32| {
-                let _: F = Default::default();
-                let _: G = Default::default();
-                x + 1
-            };
-
-            add_one(3)
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32>
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64>
-
-        // Function uses type parameter from fn in closure.
-        pub fn closure_used_fn<G: Default>() -> u32 {
-            let add_one = |x: u32| {
-                let _: G = Default::default();
-                x + 1
-            };
-
-            add_one(3)
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32>
-        //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64>
-
-        // Function uses type parameter from impl in closure.
-        pub fn closure_used_impl<G: Default>() -> u32 {
-            let add_one = |x: u32| {
-                let _: F = Default::default();
-                x + 1
-            };
-
-            add_one(3)
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G>::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G>
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G>
-
-        // Closure uses type parameter in substitutions to another function.
-        pub fn closure_used_substs() {
-            let x = || super::functions::unused::<F>();
-            x()
-        }
-
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs::{closure#0}
-        //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs
-        //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs
-    }
-}
-
-fn dispatch<T: Default>() {
-    functions::no_parameters();
-    functions::unused::<T>();
-    functions::used_binding_value::<T>();
-    functions::used_binding_type::<T>();
-    functions::used_argument::<T>(Default::default());
-    functions::used_substs::<T>();
-
-    closures::no_parameters();
-    let _ = closures::unused::<T>();
-    let _ = closures::used_parent::<T>();
-    let _ = closures::used_binding_value::<T>();
-    let _ = closures::used_binding_type::<T>();
-    let _ = closures::used_argument::<T>(Default::default());
-    let _ = closures::used_argument_closure::<T>();
-    let _ = closures::used_upvar::<T>();
-    let _ = closures::used_substs::<T>();
-
-    methods::Foo::<T>::unused_impl();
-    methods::Foo::<T>::unused_both::<T>();
-    methods::Foo::<T>::used_impl();
-    methods::Foo::<T>::used_fn::<T>();
-    methods::Foo::<T>::used_both::<T>();
-    methods::Foo::<T>::used_substs();
-    let _ = methods::Foo::<T>::closure_unused_all::<T>();
-    let _ = methods::Foo::<T>::closure_used_both::<T>();
-    let _ = methods::Foo::<T>::closure_used_impl::<T>();
-    let _ = methods::Foo::<T>::closure_used_fn::<T>();
-    let _ = methods::Foo::<T>::closure_used_substs();
-}
-
-//~ MONO_ITEM fn dispatch::<u32>
-//~ MONO_ITEM fn dispatch::<u64>
-
-pub fn foo() {
-    // Generate two copies of each function to check that where the type parameter is unused,
-    // there is only a single copy.
-    dispatch::<u32>();
-    dispatch::<u64>();
-}
-
-//~ MONO_ITEM fn foo @@ unused_type_parameters-cgu.0[External]
-
-// These are all the items that aren't relevant to the test.
-//~ MONO_ITEM fn <u32 as std::default::Default>::default
-//~ MONO_ITEM fn <u64 as std::default::Default>::default
diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs
index 35444db9558..b15fb40b68f 100644
--- a/tests/codegen/emcripten-catch-unwind.rs
+++ b/tests/codegen/emcripten-catch-unwind.rs
@@ -57,7 +57,7 @@ pub unsafe fn test_catch_unwind(
     // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8
 
     // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]]
-    // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], [[PTR_SIZE]]
+    // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr [[ALLOCA]], [[PTR_SIZE]]
     // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]]
 
     // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]])
diff --git a/tests/codegen/issues/issue-118306.rs b/tests/codegen/issues/issue-118306.rs
index 8af1c6a971c..0778ab3fde9 100644
--- a/tests/codegen/issues/issue-118306.rs
+++ b/tests/codegen/issues/issue-118306.rs
@@ -12,7 +12,7 @@ pub fn branchy(input: u64) -> u64 {
     // CHECK-LABEL: @branchy(
     // CHECK-NEXT:  start:
     // CHECK-NEXT:    [[_2:%.*]] = and i64 [[INPUT:%.*]], 3
-    // CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]]
+    // CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]]
     // CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]]
     // CHECK-NEXT:    ret i64 [[SWITCH_LOAD]]
     match input % 4 {
diff --git a/tests/codegen/issues/issue-122805.rs b/tests/codegen/issues/issue-122805.rs
index 8e03c6c8884..16dae801ee4 100644
--- a/tests/codegen/issues/issue-122805.rs
+++ b/tests/codegen/issues/issue-122805.rs
@@ -17,19 +17,19 @@
 // CHECK-LABEL: define{{.*}}void @convert(
 // CHECK-NOT: shufflevector
 // OPT2: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 2
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 2
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 4
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 4
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 6
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 6
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 8
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 8
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 10
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 10
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 12
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 12
 // OPT2-NEXT: store i16
-// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 14
+// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 14
 // OPT2-NEXT: store i16
 // OPT3LINX64: load <8 x i16>
 // OPT3LINX64-NEXT: call <8 x i16> @llvm.bswap
diff --git a/tests/codegen/reg-struct-return.rs b/tests/codegen/reg-struct-return.rs
new file mode 100644
index 00000000000..73816745ea8
--- /dev/null
+++ b/tests/codegen/reg-struct-return.rs
@@ -0,0 +1,206 @@
+// Checks how `reg-struct-return` flag works with different calling conventions:
+// Return struct with 8/16/32/64 bit size will be converted into i8/i16/i32/i64
+// (like abi_return_struct_as_int target spec).
+// x86 only.
+
+//@ revisions: ENABLED DISABLED
+//@ add-core-stubs
+//@ compile-flags: --target i686-unknown-linux-gnu -O -C no-prepopulate-passes
+//@ [ENABLED] compile-flags: -Zreg-struct-return
+//@ needs-llvm-components: x86
+
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+#![feature(no_core, lang_items)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(C)]
+pub struct Foo {
+    x: u32,
+    y: u32,
+}
+
+#[repr(C)]
+pub struct Foo1 {
+    x: u32,
+}
+
+#[repr(C)]
+pub struct Foo2 {
+    x: bool,
+    y: bool,
+    z: i16,
+}
+
+#[repr(C)]
+pub struct Foo3 {
+    x: i16,
+    y: bool,
+    z: bool,
+}
+
+#[repr(C)]
+pub struct Foo4 {
+    x: char,
+    y: bool,
+    z: u8,
+}
+
+#[repr(C)]
+pub struct Foo5 {
+    x: u32,
+    y: u16,
+    z: u8,
+    a: bool,
+}
+
+#[repr(C)]
+pub struct FooOversize1 {
+    x: u32,
+    y: u32,
+    z: u32,
+}
+
+#[repr(C)]
+pub struct FooOversize2 {
+    f0: u16,
+    f1: u16,
+    f2: u16,
+    f3: u16,
+    f4: u16,
+}
+
+#[repr(C)]
+pub struct FooFloat1 {
+    x: f32,
+    y: f32,
+}
+
+#[repr(C)]
+pub struct FooFloat2 {
+    x: f64,
+}
+
+#[repr(C)]
+pub struct FooFloat3 {
+    x: f32,
+}
+
+pub mod tests {
+    use {
+        Foo, Foo1, Foo2, Foo3, Foo4, Foo5, FooFloat1, FooFloat2, FooFloat3, FooOversize1,
+        FooOversize2,
+    };
+
+    // ENABLED: i64 @f1()
+    // DISABLED: void @f1(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "fastcall" fn f1() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // CHECK: { i32, i32 } @f2()
+    #[no_mangle]
+    pub extern "Rust" fn f2() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // ENABLED: i64 @f3()
+    // DISABLED: void @f3(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f3() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // ENABLED: i64 @f4()
+    // DISABLED: void @f4(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "cdecl" fn f4() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // ENABLED: i64 @f5()
+    // DISABLED: void @f5(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "stdcall" fn f5() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // ENABLED: i64 @f6()
+    // DISABLED: void @f6(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "thiscall" fn f6() -> Foo {
+        Foo { x: 1, y: 2 }
+    }
+
+    // ENABLED: i32 @f7()
+    // DISABLED: void @f7(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f7() -> Foo1 {
+        Foo1 { x: 1 }
+    }
+
+    // ENABLED: i32 @f8()
+    // DISABLED: void @f8(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f8() -> Foo2 {
+        Foo2 { x: true, y: false, z: 5 }
+    }
+
+    // ENABLED: i32 @f9()
+    // DISABLED: void @f9(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f9() -> Foo3 {
+        Foo3 { x: 5, y: false, z: true }
+    }
+
+    // ENABLED: i64 @f10()
+    // DISABLED: void @f10(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f10() -> Foo4 {
+        Foo4 { x: 'x', y: true, z: 170 }
+    }
+
+    // ENABLED: i64 @f11()
+    // DISABLED: void @f11(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f11() -> Foo5 {
+        Foo5 { x: 1, y: 2, z: 3, a: true }
+    }
+
+    // CHECK: void @f12(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f12() -> FooOversize1 {
+        FooOversize1 { x: 1, y: 2, z: 3 }
+    }
+
+    // CHECK: void @f13(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f13() -> FooOversize2 {
+        FooOversize2 { f0: 1, f1: 2, f2: 3, f3: 4, f4: 5 }
+    }
+
+    // ENABLED: i64 @f14()
+    // DISABLED: void @f14(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f14() -> FooFloat1 {
+        FooFloat1 { x: 1.0, y: 1.0 }
+    }
+
+    // ENABLED: double @f15()
+    // DISABLED: void @f15(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f15() -> FooFloat2 {
+        FooFloat2 { x: 1.0 }
+    }
+
+    // ENABLED: float @f16()
+    // DISABLED: void @f16(ptr {{.*}}sret
+    #[no_mangle]
+    pub extern "C" fn f16() -> FooFloat3 {
+        FooFloat3 { x: 1.0 }
+    }
+}
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
index eda807d3682..307020b42c0 100644
--- a/tests/codegen/slice-iter-nonnull.rs
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -14,7 +14,7 @@
 // CHECK-LABEL: @slice_iter_next(
 #[no_mangle]
 pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
-    // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}}
+    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
@@ -31,7 +31,7 @@ pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32
 // CHECK-LABEL: @slice_iter_next_back(
 #[no_mangle]
 pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
-    // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}}
+    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
@@ -55,7 +55,7 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'
 #[no_mangle]
 pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
     // CHECK-NOT: slice
-    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1
     // CHECK-NOT: slice
     // CHECK: insertvalue {{.+}} ptr %slice.0, 0
     // CHECK-NOT: slice
@@ -70,7 +70,7 @@ pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
 #[no_mangle]
 pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
     // CHECK-NOT: slice
-    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1
     // CHECK-NOT: slice
     // CHECK: insertvalue {{.+}} ptr %slice.0, 0
     // CHECK-NOT: slice
@@ -83,7 +83,7 @@ pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
 // CHECK-LABEL: @slice_iter_is_empty
 #[no_mangle]
 pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool {
-    // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}}
+    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
@@ -99,7 +99,7 @@ pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool {
 // CHECK-LABEL: @slice_iter_len
 #[no_mangle]
 pub fn slice_iter_len(it: &std::slice::Iter<'_, u32>) -> usize {
-    // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}}
+    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map
index c51bc6eb621..d3eed6c4f2a 100644
--- a/tests/coverage/async.cov-map
+++ b/tests/coverage/async.cov-map
@@ -1,20 +1,20 @@
 Function name: async::c
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 01, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25)
+- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 25)
 Highest counter ID seen: c0
 
 Function name: async::c::{closure#0}
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0b, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 12, 25) to (start + 1, 14)
+- Code(Counter(0)) at (prev + 11, 25) to (start + 1, 14)
 - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10)
     = (c0 - c1)
@@ -22,93 +22,93 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: async::d
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 14]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20)
+- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 20)
 Highest counter ID seen: c0
 
 Function name: async::d::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 14, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25)
+- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 25)
 Highest counter ID seen: c0
 
 Function name: async::e (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 14]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 22, 1) to (start + 0, 20)
+- Code(Zero) at (prev + 21, 1) to (start + 0, 20)
 Highest counter ID seen: (none)
 
 Function name: async::e::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 14, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 22, 20) to (start + 0, 25)
+- Code(Zero) at (prev + 21, 20) to (start + 0, 25)
 Highest counter ID seen: (none)
 
 Function name: async::f
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 14]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20)
+- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 20)
 Highest counter ID seen: c0
 
 Function name: async::f::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 14, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25)
+- Code(Counter(0)) at (prev + 23, 20) to (start + 0, 25)
 Highest counter ID seen: c0
 
 Function name: async::foo (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 00, 1e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 26, 1) to (start + 0, 30)
+- Code(Zero) at (prev + 25, 1) to (start + 0, 30)
 Highest counter ID seen: (none)
 
 Function name: async::foo::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 1e, 00, 2d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 26, 30) to (start + 0, 45)
+- Code(Zero) at (prev + 25, 30) to (start + 0, 45)
 Highest counter ID seen: (none)
 
 Function name: async::g
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23)
+- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 23)
 Highest counter ID seen: c0
 
 Function name: async::g::{closure#0} (unused)
-Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1b, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 11
-- Code(Zero) at (prev + 28, 23) to (start + 1, 12)
+- Code(Zero) at (prev + 27, 23) to (start + 1, 12)
 - Code(Zero) at (prev + 2, 9) to (start + 0, 10)
 - Code(Zero) at (prev + 0, 14) to (start + 0, 23)
 - Code(Zero) at (prev + 0, 27) to (start + 0, 28)
@@ -122,21 +122,21 @@ Number of file 0 mappings: 11
 Highest counter ID seen: (none)
 
 Function name: async::h
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 00, 16]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 16]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22)
+- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 22)
 Highest counter ID seen: c0
 
 Function name: async::h::{closure#0} (unused)
-Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (39): 0x[01, 01, 00, 07, 00, 23, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 7
-- Code(Zero) at (prev + 36, 22) to (start + 3, 12)
+- Code(Zero) at (prev + 35, 22) to (start + 3, 12)
 - Code(Zero) at (prev + 4, 9) to (start + 0, 10)
 - Code(Zero) at (prev + 0, 14) to (start + 0, 25)
 - Code(Zero) at (prev + 0, 26) to (start + 0, 27)
@@ -146,23 +146,23 @@ Number of file 0 mappings: 7
 Highest counter ID seen: (none)
 
 Function name: async::i
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 00, 13]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 00, 13]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19)
+- Code(Counter(0)) at (prev + 44, 1) to (start + 0, 19)
 Highest counter ID seen: c0
 
 Function name: async::i::{closure#0}
-Raw bytes (63): 0x[01, 01, 02, 07, 15, 0d, 11, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 11, 01, 09, 00, 0a, 19, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 11, 00, 24, 00, 26, 15, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
+Raw bytes (63): 0x[01, 01, 02, 07, 15, 0d, 11, 0b, 01, 2c, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 11, 01, 09, 00, 0a, 19, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 11, 00, 24, 00, 26, 15, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5)
 - expression 1 operands: lhs = Counter(3), rhs = Counter(4)
 Number of file 0 mappings: 11
-- Code(Counter(0)) at (prev + 45, 19) to (start + 4, 12)
+- Code(Counter(0)) at (prev + 44, 19) to (start + 4, 12)
 - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24)
 - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33)
@@ -177,14 +177,14 @@ Number of file 0 mappings: 11
 Highest counter ID seen: c7
 
 Function name: async::j
-Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
+Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 37, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 56, 1) to (start + 0, 13)
+- Code(Counter(0)) at (prev + 55, 1) to (start + 0, 13)
 - Code(Counter(0)) at (prev + 11, 11) to (start + 0, 12)
 - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27)
@@ -198,13 +198,13 @@ Number of file 0 mappings: 10
 Highest counter ID seen: c4
 
 Function name: async::j::c
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 39, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 58, 5) to (start + 1, 18)
+- Code(Counter(0)) at (prev + 57, 5) to (start + 1, 18)
 - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14)
 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14)
     = (c0 - c1)
@@ -212,30 +212,30 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: async::j::d
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 40, 05, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23)
+- Code(Counter(0)) at (prev + 64, 5) to (start + 0, 23)
 Highest counter ID seen: c0
 
 Function name: async::j::f
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23)
+- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23)
 Highest counter ID seen: c0
 
 Function name: async::k (unused)
-Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (29): 0x[01, 01, 00, 05, 00, 49, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 5
-- Code(Zero) at (prev + 74, 1) to (start + 1, 12)
+- Code(Zero) at (prev + 73, 1) to (start + 1, 12)
 - Code(Zero) at (prev + 2, 14) to (start + 0, 16)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -243,14 +243,14 @@ Number of file 0 mappings: 5
 Highest counter ID seen: (none)
 
 Function name: async::l
-Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02]
+Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 51, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 82, 1) to (start + 1, 12)
+- Code(Counter(0)) at (prev + 81, 1) to (start + 1, 12)
 - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16)
     = (c0 - (c1 + c2))
 - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16)
@@ -259,29 +259,29 @@ Number of file 0 mappings: 5
 Highest counter ID seen: c2
 
 Function name: async::m
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25)
+- Code(Counter(0)) at (prev + 89, 1) to (start + 0, 25)
 Highest counter ID seen: c0
 
 Function name: async::m::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 59, 19, 00, 22]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 90, 25) to (start + 0, 34)
+- Code(Zero) at (prev + 89, 25) to (start + 0, 34)
 Highest counter ID seen: (none)
 
 Function name: async::main
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 01, 08, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2)
+- Code(Counter(0)) at (prev + 91, 1) to (start + 8, 2)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage
index 429fb112f33..aee76b05fb7 100644
--- a/tests/coverage/async.coverage
+++ b/tests/coverage/async.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
-   LL|       |#![feature(noop_waker)]
    LL|       |#![allow(unused_assignments, dead_code)]
    LL|       |#![rustfmt::skip]
    LL|       |//@ edition: 2018
diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs
index a7f3c7cec41..da0a1c0b6f0 100644
--- a/tests/coverage/async.rs
+++ b/tests/coverage/async.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 #![feature(custom_inner_attributes)] // for #![rustfmt::skip]
-#![feature(noop_waker)]
 #![allow(unused_assignments, dead_code)]
 #![rustfmt::skip]
 //@ edition: 2018
diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map
index d6462fded13..7660f917b65 100644
--- a/tests/coverage/async2.cov-map
+++ b/tests/coverage/async2.cov-map
@@ -1,58 +1,58 @@
 Function name: async2::async_func
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 00, 17]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23)
+- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 23)
 Highest counter ID seen: c0
 
 Function name: async2::async_func::{closure#0}
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 16, 23) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 15, 23) to (start + 3, 9)
 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
 - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
 Highest counter ID seen: c1
 
 Function name: async2::async_func_just_println
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async2::async_func_just_println::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 24, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2)
+- Code(Counter(0)) at (prev + 23, 36) to (start + 2, 2)
 Highest counter ID seen: c0
 
 Function name: async2::main
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 07, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2)
+- Code(Counter(0)) at (prev + 27, 1) to (start + 7, 2)
 Highest counter ID seen: c0
 
 Function name: async2::non_async_func
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 01, 07, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 9)
 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
 - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage
index cdc171180b8..fa56072924b 100644
--- a/tests/coverage/async2.coverage
+++ b/tests/coverage/async2.coverage
@@ -1,5 +1,4 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |#![feature(noop_waker)]
    LL|       |//@ edition: 2018
    LL|       |
    LL|       |//@ aux-build: executor.rs
diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs
index f52c848f6f2..9bd4821518a 100644
--- a/tests/coverage/async2.rs
+++ b/tests/coverage/async2.rs
@@ -1,5 +1,4 @@
 #![feature(coverage_attribute)]
-#![feature(noop_waker)]
 //@ edition: 2018
 
 //@ aux-build: executor.rs
diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map
index e3309bd51b4..14ed4850d4a 100644
--- a/tests/coverage/async_block.cov-map
+++ b/tests/coverage/async_block.cov-map
@@ -1,11 +1,11 @@
 Function name: async_block::main
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 08, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 07, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 11)
+- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 11)
 - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10)
 - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19)
     = (c0 + c1)
@@ -15,13 +15,13 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: async_block::main::{closure#0}
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0a, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 09, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 10, 28) to (start + 1, 23)
+- Code(Counter(0)) at (prev + 9, 28) to (start + 1, 23)
 - Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14)
 - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14)
     = (c0 - c1)
diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage
index d9be8480d80..9e3294492cd 100644
--- a/tests/coverage/async_block.coverage
+++ b/tests/coverage/async_block.coverage
@@ -1,5 +1,4 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |#![feature(noop_waker)]
    LL|       |//@ edition: 2021
    LL|       |
    LL|       |//@ aux-build: executor.rs
diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs
index 7ae8241aa77..d1e37ab7505 100644
--- a/tests/coverage/async_block.rs
+++ b/tests/coverage/async_block.rs
@@ -1,5 +1,4 @@
 #![feature(coverage_attribute)]
-#![feature(noop_waker)]
 //@ edition: 2021
 
 //@ aux-build: executor.rs
diff --git a/tests/coverage/auxiliary/executor.rs b/tests/coverage/auxiliary/executor.rs
index fb07c8ce304..c282414fb8e 100644
--- a/tests/coverage/auxiliary/executor.rs
+++ b/tests/coverage/auxiliary/executor.rs
@@ -1,4 +1,4 @@
-#![feature(coverage_attribute, noop_waker)]
+#![feature(coverage_attribute)]
 //@ edition: 2021
 
 use core::future::Future;
diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map
index 95dbf68a191..bc1af4e42e8 100644
--- a/tests/coverage/await_ready.cov-map
+++ b/tests/coverage/await_ready.cov-map
@@ -1,19 +1,19 @@
 Function name: await_ready::await_ready
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 1e]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 1e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30)
+- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 30)
 Highest counter ID seen: c0
 
 Function name: await_ready::await_ready::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0e, 1e, 03, 0f, 05, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15)
+- Code(Counter(0)) at (prev + 14, 30) to (start + 3, 15)
 - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2)
 Highest counter ID seen: c1
 
diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage
index 7ab03e6d3de..1150d807e76 100644
--- a/tests/coverage/await_ready.coverage
+++ b/tests/coverage/await_ready.coverage
@@ -1,5 +1,4 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |#![feature(noop_waker)]
    LL|       |#![coverage(off)]
    LL|       |//@ edition: 2021
    LL|       |
diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs
index 27ee99d3989..9eaa31dedda 100644
--- a/tests/coverage/await_ready.rs
+++ b/tests/coverage/await_ready.rs
@@ -1,5 +1,4 @@
 #![feature(coverage_attribute)]
-#![feature(noop_waker)]
 #![coverage(off)]
 //@ edition: 2021
 
diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index 5b99889514c..df4652ac9ce 100644
--- a/tests/coverage/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
@@ -1,29 +1,29 @@
 Function name: closure_macro_async::load_configuration_files
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2)
+- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2)
 Highest counter ID seen: c0
 
 Function name: closure_macro_async::test
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 00, 2b]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43)
+- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 43)
 Highest counter ID seen: c0
 
 Function name: closure_macro_async::test::{closure#0}
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 38, 43) to (start + 1, 33)
+- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84)
@@ -34,7 +34,7 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: closure_macro_async::test::{closure#0}::{closure#0}
-Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
+Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 14, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
@@ -42,7 +42,7 @@ Number of expressions: 3
 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
 - expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33)
+- Code(Counter(0)) at (prev + 20, 28) to (start + 3, 33)
 - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39)
 - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22)
     = (c0 - c1)
diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage
index a8c72efac66..1e1ffec9f76 100644
--- a/tests/coverage/closure_macro_async.coverage
+++ b/tests/coverage/closure_macro_async.coverage
@@ -1,5 +1,4 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |#![feature(noop_waker)]
    LL|       |//@ edition: 2018
    LL|       |
    LL|       |//@ aux-build: executor.rs
diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs
index defd1b6d632..5dbb438424d 100644
--- a/tests/coverage/closure_macro_async.rs
+++ b/tests/coverage/closure_macro_async.rs
@@ -1,5 +1,4 @@
 #![feature(coverage_attribute)]
-#![feature(noop_waker)]
 //@ edition: 2018
 
 //@ aux-build: executor.rs
diff --git a/tests/crashes/105249.rs b/tests/crashes/105249.rs
deleted file mode 100644
index 592ed5b6dbc..00000000000
--- a/tests/crashes/105249.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ known-bug: #105249
-//@ compile-flags: -Zpolymorphize=on
-
-trait Foo<T> {
-    fn print<'a>(&'a self) where T: 'a { println!("foo"); }
-}
-
-impl<'a> Foo<&'a ()> for () { }
-
-trait Bar: for<'a> Foo<&'a ()> { }
-
-impl Bar for () {}
-
-fn main() {
-    (&() as &dyn Bar).print(); // Segfault
-}
diff --git a/tests/crashes/123809.rs b/tests/crashes/123809.rs
deleted file mode 100644
index 75abe6dc0cd..00000000000
--- a/tests/crashes/123809.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #123809
-type Positive = std::pat::pattern_type!(std::pat is 0..);
-
-pub fn main() {}
diff --git a/tests/crashes/123893.rs b/tests/crashes/123893.rs
deleted file mode 100644
index 05237d002b8..00000000000
--- a/tests/crashes/123893.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: #123893
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zinline-mir-threshold=20
-pub fn main() {
-    generic_impl::<bool>();
-}
-
-fn generic_impl<T>() {
-    trait MagicTrait {
-        const IS_BIG: bool;
-    }
-    impl<T> MagicTrait for T {
-        const IS_BIG: bool = true;
-    }
-    more_cost();
-    if T::IS_BIG {
-        big_impl::<i32>();
-    }
-}
-
-#[inline(never)]
-fn big_impl<T>() {}
-
-#[inline(never)]
-fn more_cost() {}
diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs
deleted file mode 100644
index 1b875497465..00000000000
--- a/tests/crashes/124020.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//@ known-bug: #124020
-//@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib
-
-#![feature(async_closure, noop_waker, async_trait_bounds)]
-
-use std::future::Future;
-use std::pin::pin;
-use std::task::*;
-
-pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
-    let mut fut = pin!(fut);
-    let ctx = &mut Context::from_waker(Waker::noop());
-
-    loop {
-        match fut.as_mut().poll(ctx) {
-            Poll::Pending => {}
-            Poll::Ready(t) => break t,
-        }
-    }
-}
-
-async fn call_once(f: impl AsyncFnOnce(DropMe)) {
-    f(DropMe("world")).await;
-}
-
-struct DropMe(&'static str);
-
-pub fn future() {
-    block_on(async {
-        let async_closure = async move |a: DropMe| {};
-        call_once(async_closure).await;
-    });
-}
diff --git a/tests/crashes/124436.rs b/tests/crashes/124436.rs
deleted file mode 100644
index aed830e8f0e..00000000000
--- a/tests/crashes/124436.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: rust-lang/rust#124436
-//@ compile-flags: -Zdump-mir=all -Zpolymorphize=on
-
-pub trait TraitCat {}
-pub trait TraitDog {}
-
-pub fn gamma<T: TraitCat + TraitDog>(t: [TraitDog; 32]) {}
diff --git a/tests/crashes/130425.rs b/tests/crashes/130425.rs
deleted file mode 100644
index 559b86f7bc2..00000000000
--- a/tests/crashes/130425.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: #130425
-//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on
-
-struct S<T>(T)
-where
-    [T; (
-        |_: u8| {
-            static FOO: Sync = AtomicUsize::new(0);
-            unsafe { &*(&FOO as *const _ as *const usize) }
-        },
-        1,
-    )
-        .1]: Copy;
diff --git a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py
index 2635ed487c8..9e801699fcc 100644
--- a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py
+++ b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py
@@ -1,5 +1,6 @@
 import gdb
 
+
 class PersonPrinter:
     "Print a Person"
 
@@ -11,6 +12,7 @@ class PersonPrinter:
     def to_string(self):
         return "{} is {} years old.".format(self.name, self.age)
 
+
 def lookup(val):
     lookup_tag = val.type.tag
     if lookup_tag is None:
@@ -20,4 +22,5 @@ def lookup(val):
 
     return None
 
+
 gdb.current_objfile().pretty_printers.append(lookup)
diff --git a/tests/debuginfo/embedded-visualizer-point.py b/tests/debuginfo/embedded-visualizer-point.py
index d6b1af00785..5f42957b1f8 100644
--- a/tests/debuginfo/embedded-visualizer-point.py
+++ b/tests/debuginfo/embedded-visualizer-point.py
@@ -1,5 +1,6 @@
 import gdb
 
+
 class PointPrinter:
     "Print a Point"
 
@@ -11,6 +12,7 @@ class PointPrinter:
     def to_string(self):
         return "({}, {})".format(self.x, self.y)
 
+
 def lookup(val):
     lookup_tag = val.type.tag
     if lookup_tag is None:
@@ -20,4 +22,5 @@ def lookup(val):
 
     return None
 
+
 gdb.current_objfile().pretty_printers.append(lookup)
diff --git a/tests/debuginfo/embedded-visualizer.py b/tests/debuginfo/embedded-visualizer.py
index 8e4fab61614..5fdbbda2188 100644
--- a/tests/debuginfo/embedded-visualizer.py
+++ b/tests/debuginfo/embedded-visualizer.py
@@ -1,5 +1,6 @@
 import gdb
 
+
 class LinePrinter:
     "Print a Line"
 
@@ -11,6 +12,7 @@ class LinePrinter:
     def to_string(self):
         return "({}, {})".format(self.a, self.b)
 
+
 def lookup(val):
     lookup_tag = val.type.tag
     if lookup_tag is None:
@@ -20,4 +22,5 @@ def lookup(val):
 
     return None
 
+
 gdb.current_objfile().pretty_printers.append(lookup)
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index b2168ba0c46..f28400e298f 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -1,7 +1,7 @@
 //@ edition:2021
 // skip-filecheck
 
-#![feature(async_closure, noop_waker, async_fn_traits)]
+#![feature(async_closure, async_fn_traits)]
 #![allow(unused)]
 
 use std::future::Future;
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
index ed72ca72629..a1be927e1c0 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
@@ -42,7 +42,7 @@
           StorageLive(_4);
           StorageLive(_20);
           StorageLive(_21);
-          _21 = copy ((*_1).0: u32);
+          _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
           _20 = BitAnd(move _21, const 1_u32);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
@@ -58,14 +58,14 @@
       }
   
       bb2: {
--         _5 = Minus;
-+         _5 = const Minus;
+-         _5 = core::num::flt2dec::Sign::Minus;
++         _5 = const core::num::flt2dec::Sign::Minus;
           goto -> bb3;
       }
   
       bb3: {
           StorageLive(_6);
-          _6 = copy ((*_1).4: std::option::Option<usize>);
+          _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
           _7 = discriminant(_6);
           switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
index 42d99883749..87ab71feb2f 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
@@ -42,7 +42,7 @@
           StorageLive(_4);
           StorageLive(_20);
           StorageLive(_21);
-          _21 = copy ((*_1).0: u32);
+          _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
           _20 = BitAnd(move _21, const 1_u32);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
@@ -58,14 +58,14 @@
       }
   
       bb2: {
--         _5 = Minus;
-+         _5 = const Minus;
+-         _5 = core::num::flt2dec::Sign::Minus;
++         _5 = const core::num::flt2dec::Sign::Minus;
           goto -> bb3;
       }
   
       bb3: {
           StorageLive(_6);
-          _6 = copy ((*_1).4: std::option::Option<usize>);
+          _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
           _7 = discriminant(_6);
           switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.rs b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs
new file mode 100644
index 00000000000..65d0745f494
--- /dev/null
+++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs
@@ -0,0 +1,4 @@
+pub fn baz<T>(t: std::ops::Range<T>) {
+    for _ in t {}
+}
+fn main() {}
diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr
new file mode 100644
index 00000000000..7196a1a6fed
--- /dev/null
+++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `T: Step` is not satisfied
+ --> missing-bound.rs:2:14
+  |
+2 |     for _ in t {}
+  |              ^ the trait `Step` is not implemented for `T`
+  |
+  = note: required for `std::ops::Range<T>` to implement `Iterator`
+  = note: required for `std::ops::Range<T>` to implement `IntoIterator`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs
new file mode 100644
index 00000000000..20f77f7c9aa
--- /dev/null
+++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs
@@ -0,0 +1,24 @@
+//@ only-linux
+//@ ignore-wasm32
+//@ ignore-wasm64
+// ignore-tidy-linelength
+
+// Ensure that on stable we don't suggest restricting with an unsafe trait and we continue
+// mentioning the rest of the obligation chain.
+
+use run_make_support::{diff, rust_lib_name, rustc};
+
+fn main() {
+    let out = rustc()
+        .env("RUSTC_BOOTSTRAP", "-1")
+        .input("missing-bound.rs")
+        .run_fail()
+        .assert_stderr_not_contains("help: consider restricting type parameter `T`")
+        .assert_stderr_contains(
+            r#"
+  = note: required for `std::ops::Range<T>` to implement `Iterator`
+  = note: required for `std::ops::Range<T>` to implement `IntoIterator`"#,
+        )
+        .stderr_utf8();
+    diff().expected_file("missing-bound.stderr").actual_text("(stable rustc)", &out).run()
+}
diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml
index abfa820ef27..18e5b4d7f35 100644
--- a/tests/rustdoc-gui/docblock-table-overflow.goml
+++ b/tests/rustdoc-gui/docblock-table-overflow.goml
@@ -10,12 +10,8 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"})
 
 // Checking it works on other doc blocks as well...
 
-// Logically, the ".docblock" and the "<p>" should have the same scroll width.
-compare-elements-property: (
-    "#implementations-list > details .docblock",
-    "#implementations-list > details .docblock > p",
-    ["scrollWidth"],
-)
-assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "835"})
+// Logically, the ".docblock" and the "<p>" should have the same scroll width (if we exclude the margin).
+assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 816})
+assert-property: ("#implementations-list > details .docblock > p", {"scrollWidth": 835})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"})
diff --git a/tests/rustdoc-gui/impl-block-doc.goml b/tests/rustdoc-gui/impl-block-doc.goml
new file mode 100644
index 00000000000..906ce1a37c6
--- /dev/null
+++ b/tests/rustdoc-gui/impl-block-doc.goml
@@ -0,0 +1,42 @@
+// Checks that the first sentence of an impl block doc is always visible even when the impl
+// block is collapsed.
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.ImplDoc.html"
+
+set-window-size: (900, 600)
+
+define-function: (
+    "compare-size-and-pos",
+    [nth_impl],
+    block {
+        // First we collapse the impl block.
+        store-value: (impl_path, "#implementations-list details:nth-of-type(" + |nth_impl| + ")")
+        set-property: (|impl_path|, {"open": false})
+        wait-for: |impl_path| + ":not([open])"
+
+        store-value: (impl_path, |impl_path| + " summary")
+        store-size: (|impl_path|, {"height": impl_height})
+        store-position: (|impl_path|, {"y": impl_y})
+
+        store-size: (|impl_path| + " .docblock", {"height": doc_height})
+        store-position: (|impl_path| + " .docblock", {"y": doc_y})
+
+        assert: |impl_y| + |impl_height| >= |doc_y|
+    }
+)
+
+call-function: ("compare-size-and-pos", {"nth_impl": 1})
+// Since the first impl block has a long line, we ensure that it doesn't display all of it.
+assert: (|impl_y| + |impl_height|) <= (|doc_y| + |doc_height|)
+
+call-function: ("compare-size-and-pos", {"nth_impl": 2})
+// The second impl block has a short line.
+assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|)
+
+// FIXME: Needs `if` condition to make this test check that `padding-top` on the "..." element
+// is as expected for tables.
+call-function: ("compare-size-and-pos", {"nth_impl": 3})
+assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|)
+call-function: ("compare-size-and-pos", {"nth_impl": 4})
+assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|)
+call-function: ("compare-size-and-pos", {"nth_impl": 5})
+assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|)
diff --git a/tests/rustdoc-gui/impl-doc.goml b/tests/rustdoc-gui/impl-doc.goml
index 4ec46de404f..1845255178a 100644
--- a/tests/rustdoc-gui/impl-doc.goml
+++ b/tests/rustdoc-gui/impl-doc.goml
@@ -3,7 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
 
 // The text is about 24px tall, so if there's a margin, then their position will be >24px apart
 compare-elements-position-near-false: (
-    "#implementations-list > .implementors-toggle > .docblock > p",
+    "#implementations-list > .implementors-toggle .docblock > p",
     "#implementations-list > .implementors-toggle > .impl-items",
     {"y": 24}
 )
diff --git a/tests/rustdoc-gui/item-info-overflow.goml b/tests/rustdoc-gui/item-info-overflow.goml
index 23c53c03762..c325beb6d06 100644
--- a/tests/rustdoc-gui/item-info-overflow.goml
+++ b/tests/rustdoc-gui/item-info-overflow.goml
@@ -16,7 +16,7 @@ assert-text: (
 go-to: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo2.html"
 compare-elements-property: (
     "#impl-SimpleTrait-for-LongItemInfo2 .item-info",
-    "#impl-SimpleTrait-for-LongItemInfo2 + .docblock",
+    "#impl-SimpleTrait-for-LongItemInfo2 .docblock",
     ["scrollWidth"],
 )
 assert-property: (
diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml
index 31ab281d6ce..60012db6c8c 100644
--- a/tests/rustdoc-gui/source-code-page-code-scroll.goml
+++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml
@@ -2,7 +2,7 @@
 go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 set-window-size: (800, 1000)
 // "scrollWidth" should be superior than "clientWidth".
-assert-property: ("body", {"scrollWidth": 1114, "clientWidth": 800})
+assert-property: ("body", {"scrollWidth": 1776, "clientWidth": 800})
 
 // Both properties should be equal (ie, no scroll on the code block).
-assert-property: (".example-wrap .rust", {"scrollWidth": 1000, "clientWidth": 1000})
+assert-property: (".example-wrap .rust", {"scrollWidth": 1662, "clientWidth": 1662})
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 352995c4903..91aa2c3fae5 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -652,3 +652,42 @@ pub mod long_list {
     //! * [`FromBytes`](#a) indicates that a type may safely be converted from an arbitrary byte
     //!   sequence
 }
+
+pub struct ImplDoc;
+
+/// bla sondfosdnf sdfasd fadsd fdsa f ads fad sf sad f sad fasdfsafsa df dsafasdasd fsa dfadsfasd
+/// fads fadfadd
+///
+/// bla
+impl ImplDoc {
+    pub fn bar() {}
+}
+
+/// bla
+///
+/// bla
+impl ImplDoc {
+    pub fn bar2() {}
+}
+
+// ignore-tidy-linelength
+/// | this::is::a::kinda::very::long::header::number::one | this::is::a::kinda::very::long::header::number::two | this::is::a::kinda::very::long::header::number::three |
+/// |-|-|-|
+/// | bla | bli | blob |
+impl ImplDoc {
+    pub fn bar3() {}
+}
+
+/// # h1
+///
+/// bla
+impl ImplDoc {
+    pub fn bar4() {}
+}
+
+/// * list
+/// * list
+/// * list
+impl ImplDoc {
+    pub fn bar5() {}
+}
diff --git a/tests/rustdoc-ui/issues/issue-96287.stderr b/tests/rustdoc-ui/issues/issue-96287.stderr
index 9aba0332164..40dc1cc0e70 100644
--- a/tests/rustdoc-ui/issues/issue-96287.stderr
+++ b/tests/rustdoc-ui/issues/issue-96287.stderr
@@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V`
 LL | pub type Foo<V> = impl Trait<V::Assoc>;
    |                                 ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc`
    |
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `TraitWithAssoc`
    |
 LL | pub type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>;
    |               ++++++++++++++++
@@ -16,7 +16,7 @@ LL | pub type Foo<V> = impl Trait<V::Assoc>;
    |                                 ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc`
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `TraitWithAssoc`
    |
 LL | pub type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>;
    |               ++++++++++++++++
diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr
index d87e769b505..045516d7d2f 100644
--- a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr
+++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied
 LL | pub struct Structure<C: Tec> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `C` with trait `Bar`
    |
 LL | pub struct Structure<C: Tec + Bar<5>> {
    |                             ++++++++
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied
 LL |     _field: C::BarType,
    |             ^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `C` with trait `Bar`
    |
 LL | pub struct Structure<C: Tec + Bar<5>> {
    |                             ++++++++
diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr
index ba3a8701316..aa1db4cb032 100644
--- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr
+++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr
@@ -26,12 +26,6 @@ LL | trait Parent2 { const C: &'static str; }
 LL |
 LL | fn take1(_: impl Trait1<C = "?">) {}
    |                         ^^^^^^^ ambiguous associated constant `C`
-   |
-   = help: consider introducing a new type parameter `T` and adding `where` constraints:
-               where
-                   T: Trait1,
-                   T: Parent2::C = "?",
-                   T: Parent1::C = "?"
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr
index 9713051d973..4f951ee4b4e 100644
--- a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr
+++ b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
    |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Get`
    |
 LL |     fn uhoh<T: Get>(foo: <T as Get>::Value) {}
    |              +++++
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
    |                                        ^^ the trait `Get` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Get`
    |
 LL |     fn uhoh<T: Get>(foo: <T as Get>::Value) {}
    |              +++++
diff --git a/tests/ui/associated-types/defaults-suitability.current.stderr b/tests/ui/associated-types/defaults-suitability.current.stderr
index 9c0ae59ae43..61247cee1f3 100644
--- a/tests/ui/associated-types/defaults-suitability.current.stderr
+++ b/tests/ui/associated-types/defaults-suitability.current.stderr
@@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar`
    |
 LL |     type Bar: Clone = Vec<T>;
    |               ^^^^^ required by this bound in `Foo::Bar`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL | trait Foo<T: std::clone::Clone> {
    |            +++++++++++++++++++
@@ -132,7 +132,7 @@ LL |     Self::Baz: Clone,
 ...
 LL |     type Baz = T;
    |          --- required by a bound in this associated type
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Clone`
    |
 LL |     Self::Baz: Clone, T: std::clone::Clone
    |                     ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/associated-types/defaults-suitability.next.stderr b/tests/ui/associated-types/defaults-suitability.next.stderr
index 9c0ae59ae43..61247cee1f3 100644
--- a/tests/ui/associated-types/defaults-suitability.next.stderr
+++ b/tests/ui/associated-types/defaults-suitability.next.stderr
@@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar`
    |
 LL |     type Bar: Clone = Vec<T>;
    |               ^^^^^ required by this bound in `Foo::Bar`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL | trait Foo<T: std::clone::Clone> {
    |            +++++++++++++++++++
@@ -132,7 +132,7 @@ LL |     Self::Baz: Clone,
 ...
 LL |     type Baz = T;
    |          --- required by a bound in this associated type
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Clone`
    |
 LL |     Self::Baz: Clone, T: std::clone::Clone
    |                     ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr
index 5278bdb7a5c..b2a86bb7f75 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied
 LL | impl<S, T> X<'_, T> for (S,) {
    |            ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `X`
    |
 LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
    |          ++++++++++++++++++
diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr
index 70bf90150b8..0815bdce16f 100644
--- a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr
+++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `copy`
    |
 LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
    |            ^^^^^ required by this bound in `copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
    |                  +++++++++++++++++++
diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr
index 529fc1f119a..ba4e683194f 100644
--- a/tests/ui/associated-types/issue-43784-associated-type.stderr
+++ b/tests/ui/associated-types/issue-43784-associated-type.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `Complete::Assoc`
    |
 LL |     type Assoc: Partial<Self>;
    |                 ^^^^^^^^^^^^^ required by this bound in `Complete::Assoc`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Complete for T {
    |       +++++++++++++++++++
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index 6c77ee6044f..ec2890cc8e7 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -7,7 +7,7 @@ LL | |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
    | |______________________________________________^ the trait `Foo` is not implemented for `Bug`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `Bug` with trait `Foo`
    |
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
@@ -24,7 +24,7 @@ LL | |
 LL | | }
    | |_^ the trait `Foo` is not implemented for `Bug`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `Bug` with trait `Foo`
    |
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
@@ -38,7 +38,7 @@ LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `Bug` with trait `Foo`
    |
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
@@ -61,7 +61,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
 LL |     ) -> Self::AssocType;
    |          ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `Bug` with trait `Foo`
    |
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs
index dcb710fc97c..8b50c5571c1 100644
--- a/tests/ui/async-await/async-closures/auxiliary/block-on.rs
+++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs
index 1bd2da6e899..b7d7102c287 100644
--- a/tests/ui/async-await/async-closures/inline-body.rs
+++ b/tests/ui/async-await/async-closures/inline-body.rs
@@ -6,7 +6,7 @@
 // `mir_inliner_callees` for the synthetic by-move coroutine body since
 // its def-id wasn't previously being considered.
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs
index 3032ca3c02b..1790f369c57 100644
--- a/tests/ui/async-await/async-closures/mangle.rs
+++ b/tests/ui/async-await/async-closures/mangle.rs
@@ -5,7 +5,7 @@
 //@[v0] compile-flags: -Csymbol-mangling-version=v0
 //@[legacy] compile-flags: -Csymbol-mangling-version=legacy -Zunstable-options
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure)]
 
 extern crate block_on;
 
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs
index 4e60598661f..d3884680e51 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop.rs
@@ -5,7 +5,7 @@
 // please consider modifying miri's async drop test at
 // `src/tools/miri/tests/pass/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)]
 
 //@ edition: 2021
diff --git a/tests/ui/async-await/async-fn/auxiliary/block-on.rs b/tests/ui/async-await/async-fn/auxiliary/block-on.rs
index dcb710fc97c..8b50c5571c1 100644
--- a/tests/ui/async-await/async-fn/auxiliary/block-on.rs
+++ b/tests/ui/async-await/async-fn/auxiliary/block-on.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/tests/ui/async-await/for-await-consumes-iter.rs b/tests/ui/async-await/for-await-consumes-iter.rs
index 7ea88c14cb5..fd9bbe1c115 100644
--- a/tests/ui/async-await/for-await-consumes-iter.rs
+++ b/tests/ui/async-await/for-await-consumes-iter.rs
@@ -1,5 +1,5 @@
 //@ edition: 2021
-#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)]
+#![feature(async_iterator, async_iter_from_iter, async_for_loop)]
 
 use std::future::Future;
 
diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs
index 1918e2f61aa..0b9078ae046 100644
--- a/tests/ui/async-await/for-await-passthrough.rs
+++ b/tests/ui/async-await/for-await-passthrough.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 //@ edition: 2024
-#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker,
-           gen_blocks)]
+#![feature(async_iterator, async_iter_from_iter, async_for_loop, gen_blocks)]
 
 async gen fn async_iter() -> i32 {
     let iter = core::async_iter::from_iter(0..3);
diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs
index b4af38a82b3..e69fe649fca 100644
--- a/tests/ui/async-await/for-await.rs
+++ b/tests/ui/async-await/for-await.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ edition: 2021
-#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)]
+#![feature(async_iterator, async_iter_from_iter, async_for_loop)]
 
 use std::future::Future;
 
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 9b0ce8663c2..6e36818f04f 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 //@ edition:2021
 
-#![feature(noop_waker)]
-
 use std::future::Future;
 
 trait AsyncTrait {
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
index e0901dc6886..4bafb39f600 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
@@ -2,7 +2,6 @@
 //@ known-bug: #108309
 
 #![feature(min_specialization)]
-#![feature(noop_waker)]
 
 struct MyStruct;
 
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
index 3d82f572a1a..62cca41f6cf 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -1,11 +1,11 @@
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/dont-project-to-specializable-projection.rs:14:5
+  --> $DIR/dont-project-to-specializable-projection.rs:13:5
    |
 LL |     default async fn foo(_: T) -> &'static str {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found future
    |
 note: type in trait
-  --> $DIR/dont-project-to-specializable-projection.rs:10:5
+  --> $DIR/dont-project-to-specializable-projection.rs:9:5
    |
 LL |     async fn foo(_: T) -> &'static str;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL |     async fn foo(_: T) -> &'static str;
               found signature `fn(_) -> impl Future<Output = &'static str>`
 
 error: async associated function in trait cannot be specialized
-  --> $DIR/dont-project-to-specializable-projection.rs:14:5
+  --> $DIR/dont-project-to-specializable-projection.rs:13:5
    |
 LL |     default async fn foo(_: T) -> &'static str {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL |     default async fn foo(_: T) -> &'static str {
    = note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed
 
 error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Output = ()>>` in the current scope
-  --> $DIR/dont-project-to-specializable-projection.rs:49:28
+  --> $DIR/dont-project-to-specializable-projection.rs:48:28
    |
 LL |         match fut.as_mut().poll(ctx) {
    |                            ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>`
diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr
index 317c04d2c74..8de6a825042 100644
--- a/tests/ui/async-await/issue-70818.stderr
+++ b/tests/ui/async-await/issue-70818.stderr
@@ -9,7 +9,7 @@ note: captured value is not `Send`
    |
 LL |     async { (ty, ty1) }
    |                  ^^^ has type `U` which is not `Send`
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Send`
    |
 LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
    |                  +++++++++++++++++++
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr
index f4cd7c42706..6385a8c975e 100644
--- a/tests/ui/async-await/issue-86507.stderr
+++ b/tests/ui/async-await/issue-86507.stderr
@@ -14,7 +14,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
    = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Sync`
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
    |                                       +++++++++++++++++++
diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
index 4c1de72798c..27e38ce06a4 100644
--- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
+++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
@@ -30,7 +30,7 @@ LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
    |         ^                            - you could clone this value
    |         |
    |         consider constraining this type parameter with `Clone`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL | fn copy<T: Magic + Copy>(x: T) -> (T, T) { (x, x) }
    |                  ++++++
diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr
index 1b59216b3c7..d9d92a44766 100644
--- a/tests/ui/binop/binop-consume-args.stderr
+++ b/tests/ui/binop/binop-consume-args.stderr
@@ -17,7 +17,7 @@ LL |     lhs + rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -40,7 +40,7 @@ LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs + rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn add<A: Add<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -64,7 +64,7 @@ LL |     lhs - rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -87,7 +87,7 @@ LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs - rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn sub<A: Sub<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -111,7 +111,7 @@ LL |     lhs * rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -134,7 +134,7 @@ LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs * rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn mul<A: Mul<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -158,7 +158,7 @@ LL |     lhs / rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -181,7 +181,7 @@ LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs / rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn div<A: Div<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -205,7 +205,7 @@ LL |     lhs % rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -228,7 +228,7 @@ LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs % rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn rem<A: Rem<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -252,7 +252,7 @@ LL |     lhs & rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                                   ++++++
@@ -275,7 +275,7 @@ LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                    ^ consider constraining this type parameter with `Clone`
 LL |     lhs & rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn bitand<A: BitAnd<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                                     ++++++
@@ -299,7 +299,7 @@ LL |     lhs | rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                                 ++++++
@@ -322,7 +322,7 @@ LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                  ^ consider constraining this type parameter with `Clone`
 LL |     lhs | rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn bitor<A: BitOr<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                                   ++++++
@@ -346,7 +346,7 @@ LL |     lhs ^ rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                                   ++++++
@@ -369,7 +369,7 @@ LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                    ^ consider constraining this type parameter with `Clone`
 LL |     lhs ^ rhs;
    |           --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn bitxor<A: BitXor<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                                     ++++++
@@ -393,7 +393,7 @@ LL |     lhs << rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -416,7 +416,7 @@ LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs << rhs;
    |            --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn shl<A: Shl<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
@@ -440,7 +440,7 @@ LL |     lhs >> rhs;
    |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with trait `Copy`
    |
 LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
    |                             ++++++
@@ -463,7 +463,7 @@ LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              ^ consider constraining this type parameter with `Clone`
 LL |     lhs >> rhs;
    |            --- you could clone this value
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Copy`
    |
 LL | fn shr<A: Shr<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
    |                               ++++++
diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr
index 45c7f110406..2e661c44abd 100644
--- a/tests/ui/binop/binop-move-semantics.stderr
+++ b/tests/ui/binop/binop-move-semantics.stderr
@@ -20,7 +20,7 @@ LL |     x
    |     - you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
    |                                  ++++++
@@ -40,7 +40,7 @@ help: consider cloning the value if the performance cost is acceptable
    |
 LL |     x.clone()
    |      ++++++++
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL | fn move_then_borrow<T: Add<Output=()> + Clone + Copy>(x: T) {
    |                                               ++++++
diff --git a/tests/ui/binop/issue-93927.stderr b/tests/ui/binop/issue-93927.stderr
index 9bcf2b17357..ff5ecf66be6 100644
--- a/tests/ui/binop/issue-93927.stderr
+++ b/tests/ui/binop/issue-93927.stderr
@@ -6,7 +6,7 @@ LL |     val == val
    |     |
    |     MyType<T>
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Eq`
    |
 LL | fn cond<T: PartialEq + std::cmp::Eq>(val: MyType<T>) -> bool {
    |                      ++++++++++++++
diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr
index d5d21296a3f..911c136086c 100644
--- a/tests/ui/borrowck/clone-on-ref.stderr
+++ b/tests/ui/borrowck/clone-on-ref.stderr
@@ -12,7 +12,7 @@ LL |
 LL |     drop(cloned_items);
    |          ------------ immutable borrow later used here
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Clone`
    |
 LL | fn foo<T: Default + Clone>(list: &mut Vec<T>) {
    |                   +++++++
@@ -39,7 +39,7 @@ LL | fn bar<T: std::fmt::Display>(x: T) {
    |        ^ consider constraining this type parameter with `Clone`
 LL |     let a = &x;
    |              - you could clone this value
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Clone`
    |
 LL | fn bar<T: std::fmt::Display + Clone>(x: T) {
    |                             +++++++
diff --git a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr
index 6997710ec89..e32a0c54dfe 100644
--- a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr
+++ b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr
@@ -15,7 +15,7 @@ LL | fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
 ...
 LL |             6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g,
    |                                       - you could clone this value
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn test<T: Copy, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
    |          ++++++
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
index 592aa4369ce..9915b772afa 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Foo`
    |
 LL | trait Foo : Send+Sync { }
    |             ^^^^ required by this bound in `Foo`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Send`
    |
 LL | impl <T: Sync+'static + std::marker::Send> Foo for (T,) { }
    |                       +++++++++++++++++++
@@ -27,7 +27,7 @@ note: required by a bound in `Foo`
    |
 LL | trait Foo : Send+Sync { }
    |                  ^^^^ required by this bound in `Foo`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Sync`
    |
 LL | impl <T: Send + std::marker::Sync> Foo for (T,T) { }
    |               +++++++++++++++++++
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
index 251651df4f9..39a04186981 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `RequiresRequiresShareAndSend`
    |
 LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
    |                                                          ^^^^ required by this bound in `RequiresRequiresShareAndSend`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Send`
    |
 LL | impl <T:Sync+'static + std::marker::Send> RequiresRequiresShareAndSend for X<T> { }
    |                      +++++++++++++++++++
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
index 4a25c42b583..dd273b875ae 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Foo`
    |
 LL | trait Foo : Send { }
    |             ^^^^ required by this bound in `Foo`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Send`
    |
 LL | impl <T: Sync+'static + std::marker::Send> Foo for T { }
    |                       +++++++++++++++++++
diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
index 8157590bd9e..9ceee477856 100644
--- a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
+++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `X`
    |
 LL | struct X<F> where F: FnOnce() + 'static + Send {
    |                                           ^^^^ required by this bound in `X`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Send`
    |
 LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send {
    |                                                       +++++++++++++++++++
@@ -25,7 +25,7 @@ note: required by a bound in `X`
    |
 LL | struct X<F> where F: FnOnce() + 'static + Send {
    |                                           ^^^^ required by this bound in `X`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Send`
    |
 LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send {
    |                                                       +++++++++++++++++++
diff --git a/tests/ui/closures/closure-bounds-subtype.stderr b/tests/ui/closures/closure-bounds-subtype.stderr
index 42588668e8a..34c5e0299a7 100644
--- a/tests/ui/closures/closure-bounds-subtype.stderr
+++ b/tests/ui/closures/closure-bounds-subtype.stderr
@@ -15,7 +15,7 @@ help: use parentheses to call this type parameter
    |
 LL |     take_const_owned(f());
    |                       ++
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Sync`
    |
 LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync {
    |                                                 +++++++++++++++++++
diff --git a/tests/ui/closures/issue-67123.stderr b/tests/ui/closures/issue-67123.stderr
index bdafeaef15f..7db82845ea5 100644
--- a/tests/ui/closures/issue-67123.stderr
+++ b/tests/ui/closures/issue-67123.stderr
@@ -7,7 +7,7 @@ LL |     || { t; t; };
    |          value moved here
    |
    = note: move occurs because `t` has type `T`, which does not implement the `Copy` trait
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn foo<T: Copy>(t: T) {
    |         ++++++
diff --git a/tests/ui/codegen/target-cpus.rs b/tests/ui/codegen/target-cpus.rs
index 2d46e00f803..363915c6419 100644
--- a/tests/ui/codegen/target-cpus.rs
+++ b/tests/ui/codegen/target-cpus.rs
@@ -1,3 +1,9 @@
 //@ needs-llvm-components: webassembly
 //@ compile-flags: --print=target-cpus --target=wasm32-unknown-unknown
 //@ check-pass
+
+// LLVM at HEAD has added support for the `lime1` CPU. Remove it from the
+// output so that the stdout with LLVM-at-HEAD matches the output of the LLVM
+// versions currently used by default.
+// FIXME(#133919): Once Rust upgrades to LLVM 20, remove this.
+//@ normalize-stdout-test: "(?m)^ *lime1\n" -> ""
diff --git a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr
index 88de8023f6d..01b6eaf422e 100644
--- a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr
+++ b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr
@@ -41,7 +41,7 @@ note: required by a bound in `W`
    |
 LL | struct W<T: Trait>(*mut T);
    |             ^^^^^ required by this bound in `W`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | impl<T: Trait> Trait for W<W<W<T>>> {}
    |       +++++++
diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs
deleted file mode 100644
index df454dae725..00000000000
--- a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(generic_const_exprs)]
-
-use std::str::FromStr;
-
-pub struct If<const CONDITION: bool>;
-
-pub trait True {}
-
-impl True for If<true> {}
-
-pub struct FixedI32<const FRAC: u32>;
-
-impl<const FRAC: u32> FromStr for FixedI32<FRAC>
-where
-    If<{ FRAC <= 32 }>: True,
-{
-    type Err = ();
-    fn from_str(_s: &str) -> Result<Self, Self::Err> {
-        unimplemented!()
-    }
-}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs
deleted file mode 100644
index 4b2fa1dac9b..00000000000
--- a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ aux-build:issue-94287-aux.rs
-//@ build-fail
-
-extern crate issue_94287_aux;
-
-use std::str::FromStr;
-
-fn main() {
-    let _ = <issue_94287_aux::FixedI32<16>>::from_str("");
-}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr
deleted file mode 100644
index b57779739a5..00000000000
--- a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: failed to evaluate generic const expression
-  --> $DIR/auxiliary/issue-94287-aux.rs:15:8
-   |
-LL |     If<{ FRAC <= 32 }>: True,
-   |        ^^^^^^^^^^^^^^
-   |
-   = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]`
-help: consider enabling this feature
-  --> $DIR/issue-94287.rs:1:1
-   |
-LL + #![feature(generic_const_exprs)]
-   |
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr
index b0864689f74..92a704da8b4 100644
--- a/tests/ui/const-generics/issues/issue-61336-2.stderr
+++ b/tests/ui/const-generics/issues/issue-61336-2.stderr
@@ -7,7 +7,7 @@ LL |     [x; { N }]
    = note: the `Copy` trait is required because this value will be copied for each element of the array
    = help: consider using `core::array::from_fn` to initialize the array
    = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
    |       +++++++++++++++++++
diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr
index 111afbda343..43e8f5c044a 100644
--- a/tests/ui/const-generics/issues/issue-61336.stderr
+++ b/tests/ui/const-generics/issues/issue-61336.stderr
@@ -7,7 +7,7 @@ LL |     [x; N]
    = note: the `Copy` trait is required because this value will be copied for each element of the array
    = help: consider using `core::array::from_fn` to initialize the array
    = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
    |       +++++++++++++++++++
diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
index 24572040b91..74ec052f6ec 100644
--- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
+++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
@@ -12,7 +12,7 @@ LL |     fn unsatisfied(self)
 LL |     where
 LL |         T: Bar<N>,
    |            ^^^^^^ required by this bound in `Foo::<T, N>::unsatisfied`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Bar`
    |
 LL | impl<T: Bar<N>, const N: usize> Foo<T, N> {
    |       ++++++++
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index 11e13c3efdd..bb7ff76b125 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -212,10 +212,6 @@ LL |     f()
    |     ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL |     T: ~const Fn<()> + ~const Destruct + ~const Fn(),
-   |                                        +++++++++++++
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:23:5
@@ -224,10 +220,6 @@ LL |     f()
    |     ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL |     T: ~const FnMut<()> + ~const Destruct + ~const FnMut(),
-   |                                           ++++++++++++++++
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:30:5
@@ -236,10 +228,6 @@ LL |     f()
    |     ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL |     T: ~const FnOnce<()> + ~const FnOnce(),
-   |                          +++++++++++++++++
 
 error: aborting due to 25 previous errors
 
diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
index 2bdec1bf41b..f40c1871e90 100644
--- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr
+++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -19,10 +19,6 @@ LL |             Opt::None => f(),
    |                          ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const FnOnce()>(self, f: F) -> T {
-   |                                                     +++++++++++++++++
 
 error[E0493]: destructor of `F` cannot be evaluated at compile-time
   --> $DIR/unstable-const-fn-in-libcore.rs:19:60
diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
index 3875e26b544..583820c7aa3 100644
--- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
+++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: --edition 2024
 //@ check-pass
 
-#![feature(async_iterator, gen_blocks, noop_waker)]
+#![feature(async_iterator, gen_blocks)]
 
 use std::{async_iter::AsyncIterator, pin::pin, task::{Context, Waker}};
 
diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs
index 3f7e7aa0ac2..81adb618aa5 100644
--- a/tests/ui/coroutine/async_gen_fn_iter.rs
+++ b/tests/ui/coroutine/async_gen_fn_iter.rs
@@ -2,7 +2,6 @@
 //@ run-pass
 
 #![feature(gen_blocks, async_iterator)]
-#![feature(noop_waker)]
 
 // make sure that a ridiculously simple async gen fn works as an iterator.
 
diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs
deleted file mode 100644
index 5123bf412b5..00000000000
--- a/tests/ui/coroutine/polymorphize-args.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ compile-flags: -Zpolymorphize=on
-//@ build-pass
-
-#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
-
-use std::ops::Coroutine;
-use std::pin::Pin;
-use std::thread;
-
-fn main() {
-    let mut foo = #[coroutine]
-    || yield;
-    thread::spawn(move || match Pin::new(&mut foo).resume(()) {
-        s => panic!("bad state: {:?}", s),
-    })
-    .join()
-    .unwrap();
-}
diff --git a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
index 3ef11e2c0bb..2caa779ffab 100644
--- a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
+++ b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `DropMe`
    |
 LL | struct DropMe<T: Copy>(T);
    |                  ^^^^ required by this bound in `DropMe`
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL |     [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
    |                 ~~~~~~~~~~~~~~~~~~~~~~
@@ -25,7 +25,7 @@ note: required by a bound in `DropMe`
    |
 LL | struct DropMe<T: Copy>(T);
    |                  ^^^^ required by this bound in `DropMe`
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL |     [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
    |                 ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
index 8138b86ddea..5851731e834 100644
--- a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
+++ b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `DropMe`
    |
 LL | struct DropMe<T: Copy>(T);
    |                  ^^^^ required by this bound in `DropMe`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Drop for DropMe<T>
    |       +++++++++++++++++++
@@ -25,7 +25,7 @@ note: required by a bound in `DropMe`
    |
 LL | struct DropMe<T: Copy>(T);
    |                  ^^^^ required by this bound in `DropMe`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Drop for DropMe<T>
    |       +++++++++++++++++++
diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs
index e17aef47634..be40fa30f0d 100644
--- a/tests/ui/dyn-star/dispatch-on-pin-mut.rs
+++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs
@@ -4,7 +4,6 @@
 
 #![feature(dyn_star)]
 //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
-#![feature(noop_waker)]
 
 use std::future::Future;
 
diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr
index 038f44e8b14..ab2536cc0c9 100644
--- a/tests/ui/error-codes/E0229.stderr
+++ b/tests/ui/error-codes/E0229.stderr
@@ -42,7 +42,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied
 LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I`
    |
-help: consider restricting type parameter `I`
+help: consider restricting type parameter `I` with trait `Foo`
    |
 LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {}
    |         +++++
@@ -53,7 +53,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied
 LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
    |                                       ^^ the trait `Foo` is not implemented for `I`
    |
-help: consider restricting type parameter `I`
+help: consider restricting type parameter `I` with trait `Foo`
    |
 LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {}
    |         +++++
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
index 9228a047e87..b221195a7bd 100644
--- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
@@ -25,7 +25,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -73,7 +73,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `Iterator`
    |
 LL | fn example<Q: std::iter::Iterator>(q: Q) {
    |             +++++++++++++++++++++
@@ -100,7 +100,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `Iterator`
    |
 LL | fn example<Q: std::iter::Iterator>(q: Q) {
    |             +++++++++++++++++++++
@@ -125,7 +125,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -150,7 +150,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -175,7 +175,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -200,7 +200,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -225,7 +225,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -248,7 +248,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -273,7 +273,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -296,7 +296,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -319,7 +319,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -342,7 +342,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -367,7 +367,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -392,7 +392,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
index b6a24e12bcc..90380091c50 100644
--- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
@@ -23,7 +23,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -53,7 +53,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -85,7 +85,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -117,7 +117,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -147,7 +147,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -172,7 +172,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T2`
    |
 LL | fn example<Q: T2>(q: Q) {
    |             ++++
@@ -204,7 +204,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -236,7 +236,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -261,7 +261,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T1`
    |
 LL | fn example<Q: T1>(q: Q) {
    |             ++++
@@ -286,7 +286,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T1`
    |
 LL | fn example<Q: T1>(q: Q) {
    |             ++++
@@ -318,7 +318,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
@@ -343,7 +343,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T1`
    |
 LL | fn example<Q: T1>(q: Q) {
    |             ++++
@@ -370,7 +370,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T1`
    |
 LL | fn example<Q: T1>(q: Q) {
    |             ++++
@@ -402,7 +402,7 @@ note: required by a bound in `want`
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
-help: consider restricting type parameter `Q`
+help: consider restricting type parameter `Q` with trait `T3`
    |
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
diff --git a/tests/ui/explicit-tail-calls/become-macro.rs b/tests/ui/explicit-tail-calls/become-macro.rs
new file mode 100644
index 00000000000..0a9d069ceb3
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-macro.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls, decl_macro)]
+
+macro call($f:expr $(, $args:expr)* $(,)?) {
+    ($f)($($args),*)
+}
+
+fn main() {
+    become call!(f);
+}
+
+fn f() {}
diff --git a/tests/ui/explicit-tail-calls/become-operator.fixed b/tests/ui/explicit-tail-calls/become-operator.fixed
new file mode 100644
index 00000000000..24baef42d69
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-operator.fixed
@@ -0,0 +1,42 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+#![allow(unused)]
+use std::num::Wrapping;
+use std::ops::{Not, Add, BitXorAssign};
+
+// built-ins and overloaded operators are handled differently
+
+fn f(a: u64, b: u64) -> u64 {
+    return a + b; //~ error: `become` does not support operators
+}
+
+fn g(a: String, b: &str) -> String {
+    become (a).add(b); //~ error: `become` does not support operators
+}
+
+fn h(x: u64) -> u64 {
+    return !x; //~ error: `become` does not support operators
+}
+
+fn i_do_not_know_any_more_letters(x: Wrapping<u32>) -> Wrapping<u32> {
+    become (x).not(); //~ error: `become` does not support operators
+}
+
+fn builtin_index(x: &[u8], i: usize) -> u8 {
+    return x[i] //~ error: `become` does not support operators
+}
+
+// FIXME(explicit_tail_calls): overloaded index is represented like `[&]*x.index(i)`,
+//                             and so need additional handling
+
+fn a(a: &mut u8, _: u8) {
+    return *a ^= 1; //~ error: `become` does not support operators
+}
+
+fn b(b: &mut Wrapping<u8>, _: u8) {
+    become (*b).bitxor_assign(1); //~ error: `become` does not support operators
+}
+
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/become-operator.rs b/tests/ui/explicit-tail-calls/become-operator.rs
new file mode 100644
index 00000000000..e547e979b64
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-operator.rs
@@ -0,0 +1,42 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+#![allow(unused)]
+use std::num::Wrapping;
+use std::ops::{Not, Add, BitXorAssign};
+
+// built-ins and overloaded operators are handled differently
+
+fn f(a: u64, b: u64) -> u64 {
+    become a + b; //~ error: `become` does not support operators
+}
+
+fn g(a: String, b: &str) -> String {
+    become a + b; //~ error: `become` does not support operators
+}
+
+fn h(x: u64) -> u64 {
+    become !x; //~ error: `become` does not support operators
+}
+
+fn i_do_not_know_any_more_letters(x: Wrapping<u32>) -> Wrapping<u32> {
+    become !x; //~ error: `become` does not support operators
+}
+
+fn builtin_index(x: &[u8], i: usize) -> u8 {
+    become x[i] //~ error: `become` does not support operators
+}
+
+// FIXME(explicit_tail_calls): overloaded index is represented like `[&]*x.index(i)`,
+//                             and so need additional handling
+
+fn a(a: &mut u8, _: u8) {
+    become *a ^= 1; //~ error: `become` does not support operators
+}
+
+fn b(b: &mut Wrapping<u8>, _: u8) {
+    become *b ^= 1; //~ error: `become` does not support operators
+}
+
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/become-operator.stderr b/tests/ui/explicit-tail-calls/become-operator.stderr
new file mode 100644
index 00000000000..26e4343faae
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-operator.stderr
@@ -0,0 +1,75 @@
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:11:12
+   |
+LL |     become a + b;
+   |     -------^^^^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+   = note: using `become` on a builtin operator is not useful
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:15:12
+   |
+LL |     become a + b;
+   |            ^^^^^
+   |
+help: try using the method directly
+   |
+LL |     become (a).add(b);
+   |            + ~~~~~~ +
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:19:12
+   |
+LL |     become !x;
+   |     -------^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+   = note: using `become` on a builtin operator is not useful
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:23:12
+   |
+LL |     become !x;
+   |            ^^
+   |
+help: try using the method directly
+   |
+LL |     become (x).not();
+   |            ~ +++++++
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:27:12
+   |
+LL |     become x[i]
+   |     -------^^^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+   = note: using `become` on a builtin operator is not useful
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:34:12
+   |
+LL |     become *a ^= 1;
+   |     -------^^^^^^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+   = note: using `become` on a builtin operator is not useful
+
+error: `become` does not support operators
+  --> $DIR/become-operator.rs:38:12
+   |
+LL |     become *b ^= 1;
+   |            ^^^^^^^
+   |
+help: try using the method directly
+   |
+LL |     become (*b).bitxor_assign(1);
+   |            +  ~~~~~~~~~~~~~~~~ +
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/explicit-tail-calls/become-outside.rs b/tests/ui/explicit-tail-calls/become-outside.rs
index 9c90d929111..29738bb9a29 100644
--- a/tests/ui/explicit-tail-calls/become-outside.rs
+++ b/tests/ui/explicit-tail-calls/become-outside.rs
@@ -1,5 +1,5 @@
 //@ revisions: constant array
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 #[cfg(constant)]
diff --git a/tests/ui/explicit-tail-calls/become-uncallable.fixed b/tests/ui/explicit-tail-calls/become-uncallable.fixed
new file mode 100644
index 00000000000..b77c46ea435
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-uncallable.fixed
@@ -0,0 +1,18 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+#![allow(unused)]
+
+fn f() -> u64 {
+    return 1; //~ error: `become` requires a function call
+}
+
+fn g() {
+    return { h() }; //~ error: `become` requires a function call
+}
+
+fn h() {
+    return *&g(); //~ error: `become` requires a function call
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/become-uncallable.rs b/tests/ui/explicit-tail-calls/become-uncallable.rs
new file mode 100644
index 00000000000..a73b9258aaa
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-uncallable.rs
@@ -0,0 +1,18 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+#![allow(unused)]
+
+fn f() -> u64 {
+    become 1; //~ error: `become` requires a function call
+}
+
+fn g() {
+    become { h() }; //~ error: `become` requires a function call
+}
+
+fn h() {
+    become *&g(); //~ error: `become` requires a function call
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/become-uncallable.stderr b/tests/ui/explicit-tail-calls/become-uncallable.stderr
new file mode 100644
index 00000000000..90f10b05d2a
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-uncallable.stderr
@@ -0,0 +1,44 @@
+error: `become` requires a function call
+  --> $DIR/become-uncallable.rs:7:12
+   |
+LL |     become 1;
+   |     -------^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+note: not a function call
+  --> $DIR/become-uncallable.rs:7:12
+   |
+LL |     become 1;
+   |            ^
+
+error: `become` requires a function call
+  --> $DIR/become-uncallable.rs:11:12
+   |
+LL |     become { h() };
+   |     -------^^^^^^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+note: not a function call
+  --> $DIR/become-uncallable.rs:11:12
+   |
+LL |     become { h() };
+   |            ^^^^^^^
+
+error: `become` requires a function call
+  --> $DIR/become-uncallable.rs:15:12
+   |
+LL |     become *&g();
+   |     -------^^^^^
+   |     |
+   |     help: try using `return` instead: `return`
+   |
+note: not a function call
+  --> $DIR/become-uncallable.rs:15:12
+   |
+LL |     become *&g();
+   |            ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/explicit-tail-calls/closure.fixed b/tests/ui/explicit-tail-calls/closure.fixed
new file mode 100644
index 00000000000..4af71c5d4cc
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/closure.fixed
@@ -0,0 +1,31 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+fn a() {
+    become ((|| ()) as fn() -> _)();
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn aa((): ()) {
+    become ((|()| ()) as fn(_) -> _)(());
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn aaa((): (), _: i32) {
+    become ((|(), _| ()) as fn(_, _) -> _)((), 1);
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn v((): (), ((), ()): ((), ())) -> (((), ()), ()) {
+    let f = |(), ((), ())| (((), ()), ());
+    become (f as fn(_, _) -> _)((), ((), ()));
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn main() {
+    a();
+    aa(());
+    aaa((), 1);
+    v((), ((), ()));
+}
diff --git a/tests/ui/explicit-tail-calls/closure.rs b/tests/ui/explicit-tail-calls/closure.rs
new file mode 100644
index 00000000000..79a1b5296b0
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/closure.rs
@@ -0,0 +1,31 @@
+//@ run-rustfix
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+fn a() {
+    become (|| ())();
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn aa((): ()) {
+    become (|()| ())(());
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn aaa((): (), _: i32) {
+    become (|(), _| ())((), 1);
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn v((): (), ((), ()): ((), ())) -> (((), ()), ()) {
+    let f = |(), ((), ())| (((), ()), ());
+    become f((), ((), ()));
+    //~^ ERROR: tail calling closures directly is not allowed
+}
+
+fn main() {
+    a();
+    aa(());
+    aaa((), 1);
+    v((), ((), ()));
+}
diff --git a/tests/ui/explicit-tail-calls/closure.stderr b/tests/ui/explicit-tail-calls/closure.stderr
new file mode 100644
index 00000000000..5d57bece68e
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/closure.stderr
@@ -0,0 +1,46 @@
+error: tail calling closures directly is not allowed
+  --> $DIR/closure.rs:6:5
+   |
+LL |     become (|| ())();
+   |     ^^^^^^^^^^^^^^^^
+   |
+help: try casting the closure to a function pointer type
+   |
+LL |     become ((|| ()) as fn() -> _)();
+   |            +        +++++++++++++
+
+error: tail calling closures directly is not allowed
+  --> $DIR/closure.rs:11:5
+   |
+LL |     become (|()| ())(());
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: try casting the closure to a function pointer type
+   |
+LL |     become ((|()| ()) as fn(_) -> _)(());
+   |            +          ++++++++++++++
+
+error: tail calling closures directly is not allowed
+  --> $DIR/closure.rs:16:5
+   |
+LL |     become (|(), _| ())((), 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try casting the closure to a function pointer type
+   |
+LL |     become ((|(), _| ()) as fn(_, _) -> _)((), 1);
+   |            +             +++++++++++++++++
+
+error: tail calling closures directly is not allowed
+  --> $DIR/closure.rs:22:5
+   |
+LL |     become f((), ((), ()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try casting the closure to a function pointer type
+   |
+LL |     become (f as fn(_, _) -> _)((), ((), ()));
+   |            +  +++++++++++++++++
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/explicit-tail-calls/constck.rs b/tests/ui/explicit-tail-calls/constck.rs
index 938f15f12c0..36fc3ef6f99 100644
--- a/tests/ui/explicit-tail-calls/constck.rs
+++ b/tests/ui/explicit-tail-calls/constck.rs
@@ -1,4 +1,4 @@
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 const fn f() {
diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs
index 5a105ee4eb5..0a61c90bd00 100644
--- a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs
@@ -1,4 +1,4 @@
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 pub const fn test(_: &Type) {
diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs b/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs
index 50bf6c946ca..a34482a3527 100644
--- a/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 pub const fn test(x: &Type) {
diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-move.rs b/tests/ui/explicit-tail-calls/ctfe-arg-move.rs
index 88ff3a4a5ad..610eb74a91e 100644
--- a/tests/ui/explicit-tail-calls/ctfe-arg-move.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-arg-move.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 pub const fn test(s: String) -> String {
diff --git a/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs b/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs
index 86041b66960..53d46d92bd7 100644
--- a/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 /// A very unnecessarily complicated "implementation" of the Collatz conjecture.
diff --git a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs
index 54e68b2b7f7..2a04d4893e6 100644
--- a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs
@@ -1,6 +1,6 @@
 //@ revisions: become return
 //@ [become] run-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 // This is an identity function (`|x| x`), but implemented using recursion.
diff --git a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs
index 3d69cde2989..fba4a2692af 100644
--- a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs
+++ b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs
@@ -1,4 +1,4 @@
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 pub const fn f() {
diff --git a/tests/ui/explicit-tail-calls/drop-order.rs b/tests/ui/explicit-tail-calls/drop-order.rs
index e20730446ec..242336be484 100644
--- a/tests/ui/explicit-tail-calls/drop-order.rs
+++ b/tests/ui/explicit-tail-calls/drop-order.rs
@@ -1,7 +1,7 @@
 // FIXME(explicit_tail_calls): enable this test once rustc_codegen_ssa supports tail calls
 //@ ignore-test: tail calls are not implemented in rustc_codegen_ssa yet, so this causes 🧊
 //@ run-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 use std::cell::RefCell;
 
diff --git a/tests/ui/explicit-tail-calls/in-closure.rs b/tests/ui/explicit-tail-calls/in-closure.rs
new file mode 100644
index 00000000000..b23ff5a1e05
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/in-closure.rs
@@ -0,0 +1,8 @@
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+fn main() {
+    || become f(); //~ error: `become` is not allowed in closures
+}
+
+fn f() {}
diff --git a/tests/ui/explicit-tail-calls/in-closure.stderr b/tests/ui/explicit-tail-calls/in-closure.stderr
new file mode 100644
index 00000000000..d221f732e93
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/in-closure.stderr
@@ -0,0 +1,8 @@
+error: `become` is not allowed in closures
+  --> $DIR/in-closure.rs:5:8
+   |
+LL |     || become f();
+   |        ^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/explicit-tail-calls/return-lifetime-sub.rs b/tests/ui/explicit-tail-calls/return-lifetime-sub.rs
index 1243fba9b58..df0982cc02b 100644
--- a/tests/ui/explicit-tail-calls/return-lifetime-sub.rs
+++ b/tests/ui/explicit-tail-calls/return-lifetime-sub.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 fn _f<'a>() -> &'a [u8] {
diff --git a/tests/ui/explicit-tail-calls/return-mismatches.rs b/tests/ui/explicit-tail-calls/return-mismatches.rs
index 935a1a1d28b..e48766b89b0 100644
--- a/tests/ui/explicit-tail-calls/return-mismatches.rs
+++ b/tests/ui/explicit-tail-calls/return-mismatches.rs
@@ -1,4 +1,4 @@
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 fn _f0<'a>() -> &'static [u8] {
diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.rs b/tests/ui/explicit-tail-calls/signature-mismatch.rs
new file mode 100644
index 00000000000..a32ac9d8bfe
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/signature-mismatch.rs
@@ -0,0 +1,33 @@
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+#![feature(c_variadic)]
+
+fn _f0((): ()) {
+    become _g0(); //~ error: mismatched signatures
+}
+
+fn _g0() {}
+
+
+fn _f1() {
+    become _g1(()); //~ error: mismatched signatures
+}
+
+fn _g1((): ()) {}
+
+
+extern "C" fn _f2() {
+    become _g2(); //~ error: mismatched function ABIs
+}
+
+fn _g2() {}
+
+
+fn _f3() {
+    become _g3(); //~ error: mismatched function ABIs
+}
+
+extern "C" fn _g3() {}
+
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.stderr b/tests/ui/explicit-tail-calls/signature-mismatch.stderr
new file mode 100644
index 00000000000..ba9e9dcb984
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/signature-mismatch.stderr
@@ -0,0 +1,40 @@
+error: mismatched signatures
+  --> $DIR/signature-mismatch.rs:6:5
+   |
+LL |     become _g0();
+   |     ^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn(())`
+   = note: callee signature: `fn()`
+
+error: mismatched signatures
+  --> $DIR/signature-mismatch.rs:13:5
+   |
+LL |     become _g1(());
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn()`
+   = note: callee signature: `fn(())`
+
+error: mismatched function ABIs
+  --> $DIR/signature-mismatch.rs:20:5
+   |
+LL |     become _g2();
+   |     ^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have the same ABI
+   = note: caller ABI is `"C"`, while callee ABI is `"Rust"`
+
+error: mismatched function ABIs
+  --> $DIR/signature-mismatch.rs:27:5
+   |
+LL |     become _g3();
+   |     ^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have the same ABI
+   = note: caller ABI is `"Rust"`, while callee ABI is `"C"`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/explicit-tail-calls/unsafeck.rs b/tests/ui/explicit-tail-calls/unsafeck.rs
index 872a70ca3a0..f8a8140cedc 100644
--- a/tests/ui/explicit-tail-calls/unsafeck.rs
+++ b/tests/ui/explicit-tail-calls/unsafeck.rs
@@ -1,4 +1,4 @@
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 #![feature(explicit_tail_calls)]
 
 const fn f() {
diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr
index 9a745c099c0..7dce34650d7 100644
--- a/tests/ui/generic-associated-types/generic-associated-types-where.stderr
+++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr
@@ -5,7 +5,7 @@ LL |     type Assoc2<T> = Vec<T>;
    |                      ^^^^^^ `T` cannot be formatted with the default formatter
    |
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Display`
    |
 LL |     type Assoc2<T: std::fmt::Display> = Vec<T>;
    |                  +++++++++++++++++++
diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr
index 261070d1db4..aa56505dd30 100644
--- a/tests/ui/generic-associated-types/impl_bounds.stderr
+++ b/tests/ui/generic-associated-types/impl_bounds.stderr
@@ -41,7 +41,7 @@ LL | trait Foo {
 LL |     type C where Self: Clone;
    |          ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
    |       +++++++++++++++++++
@@ -66,7 +66,7 @@ LL | trait Foo {
 LL |     fn d() where Self: Clone;
    |        ^ this trait's method doesn't have the requirement `Fooy<T>: Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
    |       +++++++++++++++++++
diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
index 55901cf450b..ac91bdcf3e9 100644
--- a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
+++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `UnsafeCopy::Item`
    |
 LL |     type Item<'a>: Copy;
    |                    ^^^^ required by this bound in `UnsafeCopy::Item`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> UnsafeCopy for T {
    |       +++++++++++++++++++
diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
index 3929e66a25a..d98071efe83 100644
--- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
+++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Fun::F`
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Fn`
    |
 LL | impl<T: Fn()> Fun for T {
    |       ++++++
diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
index 662726b8993..cd4c06a8660 100644
--- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
+++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Fun::F`
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Fn`
    |
 LL | impl<T: Fn()> Fun for T {
    |       ++++++
diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
index 34278249e35..12f9949a0d3 100644
--- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
+++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Fun::F`
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Fn`
    |
 LL | impl<T: Fn()> Fun for T {
    |       ++++++
diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
index dafe1c1d395..8b23f609530 100644
--- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
+++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Fun::F`
    |
 LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Fn`
    |
 LL | impl<T: Fn()> Fun for T {
    |       ++++++
diff --git a/tests/ui/generic-associated-types/issue-74824.current.stderr b/tests/ui/generic-associated-types/issue-74824.current.stderr
index 231136612a0..3a72db27097 100644
--- a/tests/ui/generic-associated-types/issue-74824.current.stderr
+++ b/tests/ui/generic-associated-types/issue-74824.current.stderr
@@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy`
    |
 LL |     type Copy<T>: Copy = Box<T>;
    |                   ^^^^ required by this bound in `UnsafeCopy::Copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL |     type Copy<T: std::clone::Clone>: Copy = Box<T>;
    |                +++++++++++++++++++
diff --git a/tests/ui/generic-associated-types/issue-74824.next.stderr b/tests/ui/generic-associated-types/issue-74824.next.stderr
index 231136612a0..3a72db27097 100644
--- a/tests/ui/generic-associated-types/issue-74824.next.stderr
+++ b/tests/ui/generic-associated-types/issue-74824.next.stderr
@@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy`
    |
 LL |     type Copy<T>: Copy = Box<T>;
    |                   ^^^^ required by this bound in `UnsafeCopy::Copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL |     type Copy<T: std::clone::Clone>: Copy = Box<T>;
    |                +++++++++++++++++++
diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr
index 1d7d80d1b07..6e0700639e9 100644
--- a/tests/ui/generic-associated-types/missing-bounds.stderr
+++ b/tests/ui/generic-associated-types/missing-bounds.stderr
@@ -71,7 +71,7 @@ LL |         Self(self.0 + rhs.0)
    |              |
    |              B
    |
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Add`
    |
 LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
    |       +++++++++++++++++++++++++++
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
index cf3e4cc85b9..025fcc5e170 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.stderr
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -5,7 +5,7 @@ error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
 LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
    |                                    ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `ToUnit`
    |
 LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
    |       ++++++++++++++++++++
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
index e10da26665e..da6013a4af3 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -13,7 +13,7 @@ LL | fn want_bar_for_any_ccx<B>(b: &B)
    |    -------------------- required by a bound in this function
 LL |     where B : for<'ccx> Bar<'ccx>
    |               ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
-help: consider further restricting this bound
+help: consider further restricting type parameter `B` with trait `Bar`
    |
 LL |     where B : Qux + for<'ccx> Bar<'ccx>
    |                   +++++++++++++++++++++
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr
index e60531a876b..5080d35bdde 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied
 LL |     callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `SomeTrait`
    |
 LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() {
    |                 +++++++++++++++++++++++
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied
 LL |     callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `SomeTrait`
    |
 LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() {
    |                 +++++++++++++++++++++++
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
index 5caf0eb2fd4..54ceec0aff5 100644
--- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -1,22 +1,9 @@
-error[E0283]: type annotations needed
-  --> $DIR/auto-trait-selection-freeze.rs:19:16
+error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
+  --> $DIR/auto-trait-selection-freeze.rs:19:5
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
-   |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection-freeze.rs:11:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
-help: consider specifying the generic arguments
-   |
-LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
-   |                        ++++++++
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
index d34fdcc4496..7acb9fd41b7 100644
--- a/tests/ui/impl-trait/auto-trait-selection.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -1,22 +1,9 @@
-error[E0283]: type annotations needed
-  --> $DIR/auto-trait-selection.rs:15:16
+error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
+  --> $DIR/auto-trait-selection.rs:15:5
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
-   |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection.rs:7:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
-help: consider specifying the generic arguments
-   |
-LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
-   |                        ++++++++
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
index 38c7a9ea16e..1ddbd75142f 100644
--- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
@@ -17,7 +17,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F {
    |            -------  ^^^^^^^^^^^     ^
    |            |
    |            unsatisfied trait bound introduced here
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `MyFn`
    |
 LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
    |                                        +++++++++++
@@ -43,7 +43,7 @@ LL |     fn autobatch<F>(self) -> impl Trait
 ...
 LL |         F: Callback<Self::CallbackArg>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `MyFn`
    |
 LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
    |                                        +++++++++++
@@ -68,7 +68,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F {
    |            |
    |            unsatisfied trait bound introduced here
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `MyFn`
    |
 LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
    |                                        +++++++++++
@@ -121,7 +121,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F {
    |            |
    |            unsatisfied trait bound introduced here
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `MyFn`
    |
 LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
    |                                        +++++++++++
@@ -137,7 +137,7 @@ note: required by a bound in `Callback`
    |
 LL | trait Callback<A>: MyFn<A, Output = Self::Ret> {
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback`
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `MyFn`
    |
 LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
    |                                        +++++++++++
diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr
index 2ccca0b562c..81759760bf1 100644
--- a/tests/ui/impl-trait/issue-55872-1.stderr
+++ b/tests/ui/impl-trait/issue-55872-1.stderr
@@ -17,7 +17,7 @@ LL |         (S::default(), T::default())
    |         ---------------------------- return type was inferred to be `(S, T)` here
    |
    = note: required because it appears within the type `(S, T)`
-help: consider further restricting this bound
+help: consider further restricting type parameter `S` with trait `Copy`
    |
 LL | impl<S: Default + std::marker::Copy> Bar for S {
    |                 +++++++++++++++++++
@@ -32,7 +32,7 @@ LL |         (S::default(), T::default())
    |         ---------------------------- return type was inferred to be `(S, T)` here
    |
    = note: required because it appears within the type `(S, T)`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL |     fn foo<T: Default + std::marker::Copy>() -> Self::E {
    |                       +++++++++++++++++++
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 203fbfc1d2c..1dd84f10ad8 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -33,10 +33,6 @@ LL |     fun(filter_positive());
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) {
-   |                                                                              ++++++++++++++++++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr
new file mode 100644
index 00000000000..9bc85cc7e62
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr
@@ -0,0 +1,4 @@
+error: `-Zreg-struct-return` is only supported on x86
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs
new file mode 100644
index 00000000000..b5e34bece32
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs
@@ -0,0 +1,21 @@
+//@ revisions: x86 x86_64 aarch64
+
+//@ compile-flags: -Zreg-struct-return
+
+//@[x86] check-pass
+//@[x86] needs-llvm-components: x86
+//@[x86] compile-flags: --target i686-unknown-linux-gnu
+
+//@[x86_64] check-fail
+//@[x86_64] needs-llvm-components: x86
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64] error-pattern: `-Zreg-struct-return` is only supported on x86
+
+//@[aarch64] check-fail
+//@[aarch64] needs-llvm-components: aarch64
+//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@[aarch64] error-pattern: `-Zreg-struct-return` is only supported on x86
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr
new file mode 100644
index 00000000000..9bc85cc7e62
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr
@@ -0,0 +1,4 @@
+error: `-Zreg-struct-return` is only supported on x86
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/issues/issue-6738.stderr
index 9c25c0fd9a1..f22d6a2e468 100644
--- a/tests/ui/issues/issue-6738.stderr
+++ b/tests/ui/issues/issue-6738.stderr
@@ -6,7 +6,7 @@ LL |         self.x += v.x;
    |         |
    |         cannot use `+=` on type `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `AddAssign`
    |
 LL | impl<T: std::ops::AddAssign> Foo<T> {
    |       +++++++++++++++++++++
diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr
index da9a8e5532c..a0a4ef09216 100644
--- a/tests/ui/kindck/kindck-impl-type-params.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params.stderr
@@ -12,7 +12,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |         |
    |         unsatisfied trait bound introduced here
    = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Send`
    |
 LL | fn f<T: std::marker::Send>(val: T) {
    |       +++++++++++++++++++
@@ -31,7 +31,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                |
    |                unsatisfied trait bound introduced here
    = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn f<T: std::marker::Copy>(val: T) {
    |       +++++++++++++++++++
@@ -50,7 +50,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |         |
    |         unsatisfied trait bound introduced here
    = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Send`
    |
 LL | fn g<T: std::marker::Send>(val: T) {
    |       +++++++++++++++++++
@@ -69,7 +69,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                |
    |                unsatisfied trait bound introduced here
    = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn g<T: std::marker::Copy>(val: T) {
    |       +++++++++++++++++++
diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs
index e9a5292fbbd..2159dee7463 100644
--- a/tests/ui/layout/post-mono-layout-cycle-2.rs
+++ b/tests/ui/layout/post-mono-layout-cycle-2.rs
@@ -1,7 +1,7 @@
 //@ build-fail
 //@ edition: 2021
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
index 206a6801065..3b051ef9a88 100644
--- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -6,7 +6,7 @@ LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
    |
 note: required by a bound in `FnOnce`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -19,7 +19,7 @@ LL | impl<A, B> FnMut<A> for CachedFun<A, B>
    |
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -30,7 +30,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
 LL |     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -41,7 +41,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
 LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -56,7 +56,7 @@ LL |         self.call_mut(a)
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr
index bd8095224a7..d0d4d04e28a 100644
--- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr
+++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr
@@ -4,7 +4,7 @@ error[E0277]: cannot multiply `T` by `T`
 LL | type Alias<T> = <T as std::ops::Mul>::Output;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Mul`
    |
 LL | type Alias<T: std::ops::Mul> = <T as std::ops::Mul>::Output;
    |             +++++++++++++++
diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr
index b737c0ab11f..0e00adf6ea6 100644
--- a/tests/ui/methods/filter-relevant-fn-bounds.stderr
+++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr
@@ -8,7 +8,7 @@ LL | |     where
 LL | |         F: for<'a> FnOnce(<F as Output<'a>>::Type),
    | |___________________________________________________^ the trait `for<'a> Output<'a>` is not implemented for `F`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Output`
    |
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type) + for<'a> Output<'a>,
    |                                                    ++++++++++++++++++++
@@ -19,7 +19,7 @@ error[E0277]: the trait bound `for<'a> F: Output<'a>` is not satisfied
 LL |     fn do_something_wrapper<O, F>(self, _: F)
    |        ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Output<'a>` is not implemented for `F`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Output`
    |
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type) + for<'a> Output<'a>,
    |                                                    ++++++++++++++++++++
@@ -30,7 +30,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type),
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Output`
    |
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type) + Output<'_>,
    |                                                    ++++++++++++
@@ -41,7 +41,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type),
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `F` with trait `Output`
    |
 LL |         F: for<'a> FnOnce(<F as Output<'a>>::Type) + Output<'_>,
    |                                                    ++++++++++++
diff --git a/tests/ui/mir/inline-wrong-abi.rs b/tests/ui/mir/inline-wrong-abi.rs
index 8ef0b86a26b..f015463846f 100644
--- a/tests/ui/mir/inline-wrong-abi.rs
+++ b/tests/ui/mir/inline-wrong-abi.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zmir-opt-level=0
+//@ compile-flags: -Zinline-mir=yes -Zmir-opt-level=0 -Zvalidate-mir
 
 #![feature(fn_traits, unboxed_closures)]
 struct Foo<T>(T);
diff --git a/tests/ui/mir/validate/validate-unsize-cast.stderr b/tests/ui/mir/validate/validate-unsize-cast.stderr
index cfb47b34e98..8449c6a24bd 100644
--- a/tests/ui/mir/validate/validate-unsize-cast.stderr
+++ b/tests/ui/mir/validate/validate-unsize-cast.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `CastTo`
    |
 LL | pub trait CastTo<U: ?Sized>: Unsize<U> {}
    |                              ^^^^^^^^^ required by this bound in `CastTo`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with unstable trait `Unsize`
    |
 LL | impl<T: ?Sized + std::marker::Unsize<U>, U: ?Sized> CastTo<U> for T {}
    |                ++++++++++++++++++++++++
diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr
index b3089cecfbb..80b003bbcc5 100644
--- a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr
+++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr
@@ -6,7 +6,7 @@ LL |     let _ = s == t;
    |             |
    |             &[T]
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `PartialEq`
    |
 LL | pub fn foo<T: std::cmp::PartialEq>(s: &[T], t: &[T]) {
    |             +++++++++++++++++++++
diff --git a/tests/ui/moves/issue-34721.stderr b/tests/ui/moves/issue-34721.stderr
index 94780a04c1f..9834d009d22 100644
--- a/tests/ui/moves/issue-34721.stderr
+++ b/tests/ui/moves/issue-34721.stderr
@@ -18,7 +18,7 @@ note: `Foo::zero` takes ownership of the receiver `self`, which moves `x`
    |
 LL |     fn zero(self) -> Self;
    |             ^^^^
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL |     pub fn baz<T: Foo + Copy>(x: T) -> T {
    |                       ++++++
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
index bfb855c7fb1..a5e0dd819b4 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
@@ -48,7 +48,7 @@ fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
 fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
 where
     T: A + Copy + Trait,
-    //~^ HELP consider further restricting this bound
+    //~^ HELP consider further restricting
 {
     (t, t) //~ use of moved value: `t`
 }
@@ -56,14 +56,14 @@ where
 fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
 where
     T: A + Copy + Trait,
-    //~^ HELP consider further restricting this bound
+    //~^ HELP consider further restricting
     T: B,
 {
     (t, t) //~ use of moved value: `t`
 }
 
 fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
-//~^ HELP consider further restricting this bound
+//~^ HELP consider further restricting
 where
     T: B,
 {
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
index fbe5a1d74c3..60ca03ed698 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
@@ -48,7 +48,7 @@ fn duplicate_custom_1<T>(t: S<T>) -> (S<T>, S<T>) where {
 fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
 where
     T: A,
-    //~^ HELP consider further restricting this bound
+    //~^ HELP consider further restricting
 {
     (t, t) //~ use of moved value: `t`
 }
@@ -56,14 +56,14 @@ where
 fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
 where
     T: A,
-    //~^ HELP consider further restricting this bound
+    //~^ HELP consider further restricting
     T: B,
 {
     (t, t) //~ use of moved value: `t`
 }
 
 fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
-//~^ HELP consider further restricting this bound
+//~^ HELP consider further restricting
 where
     T: B,
 {
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
index c03204c7b9f..784945dbbae 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
@@ -17,7 +17,7 @@ LL | fn duplicate_t<T>(t: T) -> (T, T) {
 ...
 LL |     (t, t)
    |      - you could clone this value
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) {
    |                 ++++++
@@ -33,7 +33,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn duplicate_opt<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) {
    |                   ++++++
@@ -49,7 +49,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn duplicate_tup1<T: Copy>(t: (T,)) -> ((T,), (T,)) {
    |                    ++++++
@@ -81,7 +81,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with traits `Copy` and `Trait`
    |
 LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
    |                      ++++++++++++++
@@ -97,7 +97,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with traits `Copy` and `Trait`
    |
 LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
    |                        ++++++++++++++
@@ -113,7 +113,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with traits `Copy` and `Trait`
    |
 LL |     T: A + Copy + Trait,
    |          ++++++++++++++
@@ -129,7 +129,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with traits `Copy` and `Trait`
    |
 LL |     T: A + Copy + Trait,
    |          ++++++++++++++
@@ -145,7 +145,7 @@ LL |     (t, t)
    |      |
    |      value moved here
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with traits `Copy` and `Trait`
    |
 LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
    |                            ++++++++++++++
@@ -169,7 +169,7 @@ LL | fn existing_colon<T:>(t: T) {
 ...
 LL |     [t, t];
    |      - you could clone this value
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn existing_colon<T: Copy>(t: T) {
    |                      ++++
@@ -193,7 +193,7 @@ LL | fn existing_colon_in_where<T>(t: T)
 ...
 LL |     [t, t];
    |      - you could clone this value
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL |     T:, T: Copy
    |       ~~~~~~~~~
diff --git a/tests/ui/phantom-auto-trait.stderr b/tests/ui/phantom-auto-trait.stderr
index 5af648f6a0c..ffd4c3a0e1a 100644
--- a/tests/ui/phantom-auto-trait.stderr
+++ b/tests/ui/phantom-auto-trait.stderr
@@ -23,7 +23,7 @@ note: required by a bound in `is_zen`
    |
 LL | fn is_zen<T: Zen>(_: T) {}
    |              ^^^ required by this bound in `is_zen`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Sync`
    |
 LL | fn not_sync<T: std::marker::Sync>(x: Guard<T>) {
    |              +++++++++++++++++++
@@ -58,7 +58,7 @@ note: required by a bound in `is_zen`
    |
 LL | fn is_zen<T: Zen>(_: T) {}
    |              ^^^ required by this bound in `is_zen`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Sync`
    |
 LL | fn nested_not_sync<T: std::marker::Sync>(x: Nested<Guard<T>>) {
    |                     +++++++++++++++++++
diff --git a/tests/ui/polymorphization/abi_mismatch.rs b/tests/ui/polymorphization/abi_mismatch.rs
deleted file mode 100644
index 22c2c162d1c..00000000000
--- a/tests/ui/polymorphization/abi_mismatch.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//! This test used to ICE: #123917
-//! The reason was that while the AST knows about two fields
-//! named `ptr`, only one exists at the layout level, so accessing
-//! `_extra_field` would use an oob index
-//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on
-
-struct NonNull<T>(*mut T);
-
-struct Token<T> {
-    ptr: *mut T,
-    ptr: NonNull<T>,
-    //~^ ERROR: `ptr` is already declared
-    _extra_field: (),
-}
-
-fn tokenize<T>(item: *mut T) -> Token<T> {
-    Token { ptr: NonNull(item), _extra_field: () }
-}
-
-fn main() {}
diff --git a/tests/ui/polymorphization/abi_mismatch.stderr b/tests/ui/polymorphization/abi_mismatch.stderr
deleted file mode 100644
index e96c737f777..00000000000
--- a/tests/ui/polymorphization/abi_mismatch.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0124]: field `ptr` is already declared
-  --> $DIR/abi_mismatch.rs:11:5
-   |
-LL |     ptr: *mut T,
-   |     ----------- `ptr` first declared here
-LL |     ptr: NonNull<T>,
-   |     ^^^^^^^^^^^^^^^ field already declared
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0124`.
diff --git a/tests/ui/polymorphization/closure_in_upvar/fn.rs b/tests/ui/polymorphization/closure_in_upvar/fn.rs
deleted file mode 100644
index 87f7bc9562b..00000000000
--- a/tests/ui/polymorphization/closure_in_upvar/fn.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//@ build-pass
-//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
-
-fn foo(f: impl Fn()) {
-    let x = |_: ()| ();
-
-    // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
-    // `x` that will differ for each instantiation despite polymorphisation of the varying
-    // argument.
-    let y = || x(());
-
-    // Consider `f` used in `foo`.
-    f();
-    // Use `y` so that it is visited in monomorphisation collection.
-    y();
-}
-
-fn entry_a() {
-    foo(|| ());
-}
-
-fn entry_b() {
-    foo(|| ());
-}
-
-fn main() {
-    entry_a();
-    entry_b();
-}
diff --git a/tests/ui/polymorphization/closure_in_upvar/fnmut.rs b/tests/ui/polymorphization/closure_in_upvar/fnmut.rs
deleted file mode 100644
index 0f49c0426ee..00000000000
--- a/tests/ui/polymorphization/closure_in_upvar/fnmut.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ build-pass
-//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
-
-fn foo(f: impl Fn()) {
-    // Mutate an upvar from `x` so that it implements `FnMut`.
-    let mut outer = 3;
-    let mut x = |_: ()| {
-        outer = 4;
-        ()
-    };
-
-    // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
-    // `x` that will differ for each instantiation despite polymorphisation of the varying
-    // argument.
-    let mut y = || x(());
-
-    // Consider `f` used in `foo`.
-    f();
-    // Use `y` so that it is visited in monomorphisation collection.
-    y();
-}
-
-fn entry_a() {
-    foo(|| ());
-}
-
-fn entry_b() {
-    foo(|| ());
-}
-
-fn main() {
-    entry_a();
-    entry_b();
-}
diff --git a/tests/ui/polymorphization/closure_in_upvar/fnonce.rs b/tests/ui/polymorphization/closure_in_upvar/fnonce.rs
deleted file mode 100644
index 85c7ce2ce27..00000000000
--- a/tests/ui/polymorphization/closure_in_upvar/fnonce.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ build-pass
-//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
-
-fn foo(f: impl Fn()) {
-    // Move a non-copy type into `x` so that it implements `FnOnce`.
-    let outer = Vec::<u32>::new();
-    let x = move |_: ()| {
-        let inner = outer;
-        ()
-    };
-
-    // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
-    // `x` that will differ for each instantiation despite polymorphisation of the varying
-    // argument.
-    let y = || x(());
-
-    // Consider `f` used in `foo`.
-    f();
-    // Use `y` so that it is visited in monomorphisation collection.
-    y();
-}
-
-fn entry_a() {
-    foo(|| ());
-}
-
-fn entry_b() {
-    foo(|| ());
-}
-
-fn main() {
-    entry_a();
-    entry_b();
-}
diff --git a/tests/ui/polymorphization/closure_in_upvar/other.rs b/tests/ui/polymorphization/closure_in_upvar/other.rs
deleted file mode 100644
index b008fc49af4..00000000000
--- a/tests/ui/polymorphization/closure_in_upvar/other.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//@ build-pass
-//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
-
-fn y_uses_f(f: impl Fn()) {
-    let x = |_: ()| ();
-
-    let y = || {
-        f();
-        x(());
-    };
-
-    f();
-    y();
-}
-
-fn x_uses_f(f: impl Fn()) {
-    let x = |_: ()| { f(); };
-
-    let y = || x(());
-
-    f();
-    y();
-}
-
-fn entry_a() {
-    x_uses_f(|| ());
-    y_uses_f(|| ());
-}
-
-fn entry_b() {
-    x_uses_f(|| ());
-    y_uses_f(|| ());
-}
-
-fn main() {
-    entry_a();
-    entry_b();
-}
diff --git a/tests/ui/polymorphization/const_parameters/closures.rs b/tests/ui/polymorphization/const_parameters/closures.rs
deleted file mode 100644
index 8bdb7381454..00000000000
--- a/tests/ui/polymorphization/const_parameters/closures.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(generic_const_exprs, rustc_attrs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
-
-// This test checks that the polymorphization analysis correctly detects unused const
-// parameters in closures.
-
-// Function doesn't have any generic parameters to be unused.
-#[rustc_polymorphize_error]
-pub fn no_parameters() {
-    let _ = || {};
-}
-
-// Function has an unused generic parameter in parent and closure.
-#[rustc_polymorphize_error]
-pub fn unused<const T: usize>() -> usize {
-    //~^ ERROR item has unused generic parameters
-    let add_one = |x: usize| x + 1;
-    //~^ ERROR item has unused generic parameters
-    add_one(3)
-}
-
-// Function has an unused generic parameter in closure, but not in parent.
-#[rustc_polymorphize_error]
-pub fn used_parent<const T: usize>() -> usize {
-    let x: usize = T;
-    let add_one = |x: usize| x + 1;
-    //~^ ERROR item has unused generic parameters
-    x + add_one(3)
-}
-
-// Function uses generic parameter in value of a binding in closure.
-#[rustc_polymorphize_error]
-pub fn used_binding<const T: usize>() -> usize {
-    let x = || {
-        let y: usize = T;
-        y
-    };
-
-    x()
-}
-
-// Closure uses a value as an upvar, which used the generic parameter.
-#[rustc_polymorphize_error]
-pub fn unused_upvar<const T: usize>() -> usize {
-    let x: usize = T;
-    let y = || x;
-    //~^ ERROR item has unused generic parameters
-    y()
-}
-
-// Closure uses generic parameter in substitutions to another function.
-#[rustc_polymorphize_error]
-pub fn used_substs<const T: usize>() -> usize {
-    let x = || unused::<T>();
-    x()
-}
-
-fn main() {
-    no_parameters();
-    let _ = unused::<1>();
-    let _ = used_parent::<1>();
-    let _ = used_binding::<1>();
-    let _ = unused_upvar::<1>();
-    let _ = used_substs::<1>();
-}
diff --git a/tests/ui/polymorphization/const_parameters/closures.stderr b/tests/ui/polymorphization/const_parameters/closures.stderr
deleted file mode 100644
index 4e927f7732f..00000000000
--- a/tests/ui/polymorphization/const_parameters/closures.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/closures.rs:3:12
-   |
-LL | #![feature(generic_const_exprs, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:19:19
-   |
-LL | pub fn unused<const T: usize>() -> usize {
-   |               -------------- generic parameter `T` is unused
-LL |
-LL |     let add_one = |x: usize| x + 1;
-   |                   ^^^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:17:8
-   |
-LL | pub fn unused<const T: usize>() -> usize {
-   |        ^^^^^^ -------------- generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:28:19
-   |
-LL | pub fn used_parent<const T: usize>() -> usize {
-   |                    -------------- generic parameter `T` is unused
-LL |     let x: usize = T;
-LL |     let add_one = |x: usize| x + 1;
-   |                   ^^^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:48:13
-   |
-LL | pub fn unused_upvar<const T: usize>() -> usize {
-   |                     -------------- generic parameter `T` is unused
-LL |     let x: usize = T;
-LL |     let y = || x;
-   |             ^^
-
-error: aborting due to 4 previous errors; 1 warning emitted
-
diff --git a/tests/ui/polymorphization/const_parameters/functions.rs b/tests/ui/polymorphization/const_parameters/functions.rs
deleted file mode 100644
index 6535e3f081d..00000000000
--- a/tests/ui/polymorphization/const_parameters/functions.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(generic_const_exprs, rustc_attrs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
-
-// This test checks that the polymorphization analysis correctly detects unused const
-// parameters in functions.
-
-// Function doesn't have any generic parameters to be unused.
-#[rustc_polymorphize_error]
-pub fn no_parameters() {}
-
-// Function has an unused generic parameter.
-#[rustc_polymorphize_error]
-pub fn unused<const T: usize>() {
-    //~^ ERROR item has unused generic parameters
-}
-
-// Function uses generic parameter in value of a binding.
-#[rustc_polymorphize_error]
-pub fn used_binding<const T: usize>() -> usize {
-    let x: usize = T;
-    x
-}
-
-// Function uses generic parameter in substitutions to another function.
-#[rustc_polymorphize_error]
-pub fn used_substs<const T: usize>() {
-    unused::<T>()
-}
-
-fn main() {
-    no_parameters();
-    unused::<1>();
-    used_binding::<1>();
-    used_substs::<1>();
-}
diff --git a/tests/ui/polymorphization/const_parameters/functions.stderr b/tests/ui/polymorphization/const_parameters/functions.stderr
deleted file mode 100644
index a3033d1dcab..00000000000
--- a/tests/ui/polymorphization/const_parameters/functions.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/functions.rs:3:12
-   |
-LL | #![feature(generic_const_exprs, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: item has unused generic parameters
-  --> $DIR/functions.rs:15:8
-   |
-LL | pub fn unused<const T: usize>() {
-   |        ^^^^^^ -------------- generic parameter `T` is unused
-
-error: aborting due to 1 previous error; 1 warning emitted
-
diff --git a/tests/ui/polymorphization/coroutine.rs b/tests/ui/polymorphization/coroutine.rs
deleted file mode 100644
index 22ceadfb194..00000000000
--- a/tests/ui/polymorphization/coroutine.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on -Zinline-mir=off
-#![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
-
-use std::marker::Unpin;
-use std::ops::{Coroutine, CoroutineState};
-use std::pin::Pin;
-
-enum YieldOrReturn<Y, R> {
-    Yield(Y),
-    Return(R),
-}
-
-fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>>
-where
-    T: Coroutine<(), Yield = Y, Return = R> + Unpin,
-{
-    let mut results = Vec::new();
-    loop {
-        match Pin::new(&mut t).resume(()) {
-            CoroutineState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)),
-            CoroutineState::Complete(returned) => {
-                results.push(YieldOrReturn::Return(returned));
-                return results;
-            }
-        }
-    }
-}
-
-// This test checks that the polymorphization analysis functions on coroutines.
-
-#[rustc_polymorphize_error]
-pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
-    #[coroutine]
-    || {
-        //~^ ERROR item has unused generic parameters
-        yield 1;
-        2
-    }
-}
-
-#[rustc_polymorphize_error]
-pub fn used_type_in_yield<Y: Default>() -> impl Coroutine<(), Yield = Y, Return = u32> + Unpin {
-    #[coroutine]
-    || {
-        yield Y::default();
-        2
-    }
-}
-
-#[rustc_polymorphize_error]
-pub fn used_type_in_return<R: Default>() -> impl Coroutine<(), Yield = u32, Return = R> + Unpin {
-    #[coroutine]
-    || {
-        yield 3;
-        R::default()
-    }
-}
-
-#[rustc_polymorphize_error]
-pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
-    #[coroutine]
-    || {
-        //~^ ERROR item has unused generic parameters
-        yield 1;
-        2
-    }
-}
-
-#[rustc_polymorphize_error]
-pub fn used_const_in_yield<const Y: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
-{
-    #[coroutine]
-    || {
-        yield Y;
-        2
-    }
-}
-
-#[rustc_polymorphize_error]
-pub fn used_const_in_return<const R: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
-{
-    #[coroutine]
-    || {
-        yield 4;
-        R
-    }
-}
-
-fn main() {
-    finish(unused_type::<u32>());
-    finish(used_type_in_yield::<u32>());
-    finish(used_type_in_return::<u32>());
-    finish(unused_const::<1u32>());
-    finish(used_const_in_yield::<1u32>());
-    finish(used_const_in_return::<1u32>());
-}
diff --git a/tests/ui/polymorphization/coroutine.stderr b/tests/ui/polymorphization/coroutine.stderr
deleted file mode 100644
index 07e29184226..00000000000
--- a/tests/ui/polymorphization/coroutine.stderr
+++ /dev/null
@@ -1,29 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coroutine.rs:3:12
-   |
-LL | #![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: item has unused generic parameters
-  --> $DIR/coroutine.rs:36:5
-   |
-LL | pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
-   |                    - generic parameter `T` is unused
-LL |     #[coroutine]
-LL |     || {
-   |     ^^
-
-error: item has unused generic parameters
-  --> $DIR/coroutine.rs:64:5
-   |
-LL | pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
-   |                     ------------ generic parameter `T` is unused
-LL |     #[coroutine]
-LL |     || {
-   |     ^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
diff --git a/tests/ui/polymorphization/drop_shims/simple.rs b/tests/ui/polymorphization/drop_shims/simple.rs
deleted file mode 100644
index e51765bf432..00000000000
--- a/tests/ui/polymorphization/drop_shims/simple.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ check-pass
-//@ compile-flags:-Zpolymorphize=on
-
-pub struct OnDrop<F: Fn()>(pub F);
-
-impl<F: Fn()> Drop for OnDrop<F> {
-    fn drop(&mut self) { }
-}
-
-fn foo<R, S: FnOnce()>(
-    _: R,
-    _: S,
-) {
-    let bar = || {
-        let _ = OnDrop(|| ());
-    };
-    bar();
-}
-
-fn main() {
-    foo(3u32, || {});
-}
diff --git a/tests/ui/polymorphization/drop_shims/transitive.rs b/tests/ui/polymorphization/drop_shims/transitive.rs
deleted file mode 100644
index 331451e1a15..00000000000
--- a/tests/ui/polymorphization/drop_shims/transitive.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//@ check-pass
-//@ compile-flags:-Zpolymorphize=on
-
-pub struct OnDrop<F: Fn()>(pub F);
-
-impl<F: Fn()> Drop for OnDrop<F> {
-    fn drop(&mut self) { }
-}
-
-fn bar<F: FnOnce()>(f: F) {
-    let _ = OnDrop(|| ());
-    f()
-}
-
-fn foo<R, S: FnOnce()>(
-    _: R,
-    _: S,
-) {
-    let bar = || {
-        bar(|| {})
-    };
-    bar();
-}
-
-fn main() {
-    foo(3u32, || {});
-}
diff --git a/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs b/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs
deleted file mode 100644
index 4557c7e517c..00000000000
--- a/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// issue: rust-lang/rust#90192
-// ICE assertion failed: matches!(ty.kind(), ty :: Param(_))
-//@ compile-flags:-Zpolymorphize=on -Zmir-opt-level=3
-//@ build-pass
-
-fn test<T>() {
-    std::mem::size_of::<T>();
-}
-
-pub fn foo<T>(_: T) -> &'static fn() {
-    &(test::<T> as fn())
-}
-
-fn outer<T>() {
-    foo(|| ());
-}
-
-fn main() {
-    outer::<u8>();
-}
diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.rs b/tests/ui/polymorphization/inline-incorrect-early-bound.rs
deleted file mode 100644
index e69e4a4faa0..00000000000
--- a/tests/ui/polymorphization/inline-incorrect-early-bound.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// This test demonstrates an ICE that may occur when we try to resolve the instance
-// of a impl that has different generics than the trait it's implementing. This ensures
-// we first check that the args are compatible before resolving the body, just like
-// we do in projection before substituting a GAT.
-//
-// When polymorphization is enabled, we check the optimized MIR for unused parameters.
-// This will invoke the inliner, leading to this ICE.
-
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes
-
-trait Trait {
-    fn foo<'a, K: 'a>(self, _: K);
-}
-
-impl Trait for () {
-    #[inline]
-    fn foo<K>(self, _: K) {
-        //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration
-        todo!();
-    }
-}
-
-pub fn qux<T>() {
-    ().foo(());
-}
-
-fn main() {}
diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.stderr b/tests/ui/polymorphization/inline-incorrect-early-bound.stderr
deleted file mode 100644
index 3a1d05e8a36..00000000000
--- a/tests/ui/polymorphization/inline-incorrect-early-bound.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
-  --> $DIR/inline-incorrect-early-bound.rs:17:11
-   |
-LL |     fn foo<'a, K: 'a>(self, _: K);
-   |           -----------
-   |           |       |
-   |           |       this bound might be missing in the impl
-   |           lifetimes in impl do not match this method in trait
-...
-LL |     fn foo<K>(self, _: K) {
-   |           ^^^ lifetimes do not match method in trait
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/polymorphization/inline-tainted-body.rs b/tests/ui/polymorphization/inline-tainted-body.rs
deleted file mode 100644
index 13aec97e22b..00000000000
--- a/tests/ui/polymorphization/inline-tainted-body.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
-
-#![feature(unboxed_closures)]
-
-use std::sync::Arc;
-
-pub struct WeakOnce<T>();
-//~^ ERROR type parameter `T` is never used
-
-impl<T> WeakOnce<T> {
-    extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
-    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
-    //~| ERROR mismatched types
-
-    pub fn get(&self) -> Arc<T> {
-        self.try_get()
-            .unwrap_or_else(|| panic!("Singleton {} not available", std::any::type_name::<T>()))
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/polymorphization/inline-tainted-body.stderr b/tests/ui/polymorphization/inline-tainted-body.stderr
deleted file mode 100644
index 5c3bd70adae..00000000000
--- a/tests/ui/polymorphization/inline-tainted-body.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0392]: type parameter `T` is never used
-  --> $DIR/inline-tainted-body.rs:7:21
-   |
-LL | pub struct WeakOnce<T>();
-   |                     ^ unused type parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
-
-error: functions with the "rust-call" ABI must take a single non-self tuple argument
-  --> $DIR/inline-tainted-body.rs:11:35
-   |
-LL |     extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
-   |                                   ^^^^^
-
-error[E0308]: mismatched types
-  --> $DIR/inline-tainted-body.rs:11:45
-   |
-LL |     extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
-   |                           -------           ^^^^^^^^^^^^^^ expected `Option<Arc<T>>`, found `()`
-   |                           |
-   |                           implicitly returns `()` as its body has no tail or `return` expression
-   |
-   = note:   expected enum `Option<Arc<T>>`
-           found unit type `()`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/polymorphization/issue-74614.rs b/tests/ui/polymorphization/issue-74614.rs
deleted file mode 100644
index 3ed030b5778..00000000000
--- a/tests/ui/polymorphization/issue-74614.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ compile-flags:-Zpolymorphize=on
-//@ build-pass
-
-fn test<T>() {
-    std::mem::size_of::<T>();
-}
-
-pub fn foo<T>(_: T) -> &'static fn() {
-    &(test::<T> as fn())
-}
-
-fn outer<T>() {
-    foo(|| ());
-}
-
-fn main() {
-    outer::<u8>();
-}
diff --git a/tests/ui/polymorphization/issue-74636.rs b/tests/ui/polymorphization/issue-74636.rs
deleted file mode 100644
index b06b5fdb004..00000000000
--- a/tests/ui/polymorphization/issue-74636.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ compile-flags:-Zpolymorphize=on
-//@ build-pass
-
-use std::any::TypeId;
-
-pub fn foo<T: 'static>(_: T) -> TypeId {
-    TypeId::of::<T>()
-}
-
-fn outer<T: 'static>() {
-    foo(|| ());
-}
-
-fn main() {
-    outer::<u8>();
-}
diff --git a/tests/ui/polymorphization/lifetimes.rs b/tests/ui/polymorphization/lifetimes.rs
deleted file mode 100644
index 5f8aa13d61d..00000000000
--- a/tests/ui/polymorphization/lifetimes.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(rustc_attrs)]
-
-// This test checks that the polymorphization analysis doesn't break when the
-// function/closure doesn't just have generic parameters.
-
-// Function has an unused generic parameter.
-#[rustc_polymorphize_error]
-pub fn unused<'a, T>(_: &'a u32) {
-    //~^ ERROR item has unused generic parameters
-}
-
-#[rustc_polymorphize_error]
-pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
-    let _: T = Default::default();
-    let add_one = |x: u32| x + 1;
-    //~^ ERROR item has unused generic parameters
-    add_one(3)
-}
-
-fn main() {
-    unused::<u32>(&3);
-    used::<u32>(&3);
-}
diff --git a/tests/ui/polymorphization/lifetimes.stderr b/tests/ui/polymorphization/lifetimes.stderr
deleted file mode 100644
index 4773dd4fa2e..00000000000
--- a/tests/ui/polymorphization/lifetimes.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/lifetimes.rs:10:8
-   |
-LL | pub fn unused<'a, T>(_: &'a u32) {
-   |        ^^^^^^     - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/lifetimes.rs:17:19
-   |
-LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
-   |                 - generic parameter `T` is unused
-LL |     let _: T = Default::default();
-LL |     let add_one = |x: u32| x + 1;
-   |                   ^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/polymorphization/normalized_sig_types.rs b/tests/ui/polymorphization/normalized_sig_types.rs
deleted file mode 100644
index c8a5b3e9295..00000000000
--- a/tests/ui/polymorphization/normalized_sig_types.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-//@ build-pass
-//@ compile-flags:-Zpolymorphize=on
-
-pub trait ParallelIterator: Sized {
-    fn drive<C: Consumer<()>>(_: C) {
-        C::into_folder();
-    }
-}
-
-pub trait Consumer<T>: Sized {
-    type Result;
-    fn into_folder() -> Self::Result;
-}
-
-impl ParallelIterator for () {}
-
-impl<F: Fn(), T> Consumer<T> for F {
-    type Result = ();
-    fn into_folder() -> Self::Result {
-        unimplemented!()
-    }
-}
-
-fn main() {
-    <()>::drive(|| ());
-}
diff --git a/tests/ui/polymorphization/predicates.rs b/tests/ui/polymorphization/predicates.rs
deleted file mode 100644
index 1ba68f2698e..00000000000
--- a/tests/ui/polymorphization/predicates.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-//@ build-fail
-//@ compile-flags: -Copt-level=0 -Zpolymorphize=on
-
-#![feature(rustc_attrs)]
-
-// This test checks that `T` is considered used in `foo`, because it is used in a predicate for
-// `I`, which is used.
-
-#[rustc_polymorphize_error]
-fn bar<I>() {
-    //~^ ERROR item has unused generic parameters
-}
-
-#[rustc_polymorphize_error]
-fn foo<I, T>(_: I)
-//~^ ERROR item has unused generic parameters
-where
-    I: Iterator<Item = T>,
-{
-    bar::<I>()
-}
-
-#[rustc_polymorphize_error]
-fn baz<I, T>(_: I)
-//~^ ERROR item has unused generic parameters
-where
-    std::iter::Repeat<I>: Iterator<Item = T>,
-{
-    bar::<I>()
-}
-
-// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and
-// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates.
-
-pub(crate) struct Foo<'a, I, E>(I, &'a E);
-
-impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
-where
-    I: Iterator<Item = &'a (T, E)>,
-{
-    type Item = T;
-
-    #[rustc_polymorphize_error]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.find(|_| true)
-        //~^ ERROR item has unused generic parameters
-    }
-}
-
-// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered
-// used because `B` is now used.
-
-trait Baz<Z> {}
-
-impl Baz<u16> for u8 {}
-impl Baz<u32> for u16 {}
-
-#[rustc_polymorphize_error]
-fn quux<A, B, C: Default>() -> usize
-//~^ ERROR item has unused generic parameters
-where
-    A: Baz<B>,
-    B: Baz<C>,
-{
-    std::mem::size_of::<C>()
-}
-
-// Finally, check that `F` is considered used because `G` is used when neither are in the self-ty
-// of the predicate.
-
-trait Foobar<F, G> {}
-
-impl Foobar<u32, u32> for () {}
-
-#[rustc_polymorphize_error]
-fn foobar<F, G>() -> usize
-//~^ ERROR item has unused generic parameters
-where
-    (): Foobar<F, G>,
-{
-    std::mem::size_of::<G>()
-}
-
-fn main() {
-    let x = &[2u32];
-    foo(x.iter());
-    baz(x.iter());
-
-    let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
-    let _ = a.next();
-
-    let _ = quux::<u8, u16, u32>();
-
-    let _ = foobar::<u32, u32>();
-}
diff --git a/tests/ui/polymorphization/predicates.stderr b/tests/ui/polymorphization/predicates.stderr
deleted file mode 100644
index a3b2f75b12d..00000000000
--- a/tests/ui/polymorphization/predicates.stderr
+++ /dev/null
@@ -1,45 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:10:4
-   |
-LL | fn bar<I>() {
-   |    ^^^ - generic parameter `I` is unused
-
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:15:4
-   |
-LL | fn foo<I, T>(_: I)
-   |    ^^^    - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:24:4
-   |
-LL | fn baz<I, T>(_: I)
-   |    ^^^    - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:45:19
-   |
-LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
-   |          -         - generic parameter `E` is unused
-   |          |
-   |          generic parameter `I` is unused
-...
-LL |         self.find(|_| true)
-   |                   ^^^
-
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:59:4
-   |
-LL | fn quux<A, B, C: Default>() -> usize
-   |    ^^^^ -  - generic parameter `B` is unused
-   |         |
-   |         generic parameter `A` is unused
-
-error: item has unused generic parameters
-  --> $DIR/predicates.rs:76:4
-   |
-LL | fn foobar<F, G>() -> usize
-   |    ^^^^^^ - generic parameter `F` is unused
-
-error: aborting due to 6 previous errors
-
diff --git a/tests/ui/polymorphization/promoted-function-1.rs b/tests/ui/polymorphization/promoted-function-1.rs
deleted file mode 100644
index 8c2ed621249..00000000000
--- a/tests/ui/polymorphization/promoted-function-1.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ build-fail
-//@ compile-flags: -Zpolymorphize=on
-#![crate_type = "lib"]
-#![feature(rustc_attrs)]
-
-fn foo<'a>(_: &'a ()) {}
-
-#[rustc_polymorphize_error]
-pub fn test<T>() {
-    //~^ ERROR item has unused generic parameters
-    foo(&());
-}
diff --git a/tests/ui/polymorphization/promoted-function-1.stderr b/tests/ui/polymorphization/promoted-function-1.stderr
deleted file mode 100644
index 8ab0320aafe..00000000000
--- a/tests/ui/polymorphization/promoted-function-1.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/promoted-function-1.rs:9:8
-   |
-LL | pub fn test<T>() {
-   |        ^^^^ - generic parameter `T` is unused
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/polymorphization/promoted-function-2.rs b/tests/ui/polymorphization/promoted-function-2.rs
deleted file mode 100644
index aaae7064f37..00000000000
--- a/tests/ui/polymorphization/promoted-function-2.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![crate_type = "lib"]
-#![feature(generic_const_exprs, rustc_attrs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
-
-#[rustc_polymorphize_error]
-fn test<T>() {
-    //~^ ERROR item has unused generic parameters
-    let x = [0; 3 + 4];
-}
-
-pub fn caller() {
-    test::<String>();
-    test::<Vec<String>>();
-}
diff --git a/tests/ui/polymorphization/promoted-function-2.stderr b/tests/ui/polymorphization/promoted-function-2.stderr
deleted file mode 100644
index a5d3bee11d9..00000000000
--- a/tests/ui/polymorphization/promoted-function-2.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/promoted-function-2.rs:4:12
-   |
-LL | #![feature(generic_const_exprs, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: item has unused generic parameters
-  --> $DIR/promoted-function-2.rs:8:4
-   |
-LL | fn test<T>() {
-   |    ^^^^ - generic parameter `T` is unused
-
-error: aborting due to 1 previous error; 1 warning emitted
-
diff --git a/tests/ui/polymorphization/promoted-function-3.rs b/tests/ui/polymorphization/promoted-function-3.rs
deleted file mode 100644
index 2ac06d5a139..00000000000
--- a/tests/ui/polymorphization/promoted-function-3.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ run-pass
-//@ compile-flags: -Zpolymorphize=on -Zmir-opt-level=4
-
-fn caller<T, U>() -> &'static usize {
-    callee::<U>()
-}
-
-fn callee<T>() -> &'static usize {
-    &std::mem::size_of::<T>()
-}
-
-fn main() {
-    assert_eq!(caller::<(), ()>(), &0);
-}
diff --git a/tests/ui/polymorphization/promoted-function.rs b/tests/ui/polymorphization/promoted-function.rs
deleted file mode 100644
index 057daf4e757..00000000000
--- a/tests/ui/polymorphization/promoted-function.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ run-pass
-//@ compile-flags:-Zpolymorphize=on
-
-fn fop<T>() {}
-
-fn bar<T>() -> &'static fn() {
-    &(fop::<T> as fn())
-}
-pub const FN: &'static fn() = &(fop::<i32> as fn());
-
-fn main() {
-    bar::<u32>();
-    bar::<i32>();
-    (FN)();
-}
diff --git a/tests/ui/polymorphization/symbol-ambiguity.rs b/tests/ui/polymorphization/symbol-ambiguity.rs
deleted file mode 100644
index 183837f9961..00000000000
--- a/tests/ui/polymorphization/symbol-ambiguity.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ build-pass
-//@ compile-flags: -Zpolymorphize=on -Csymbol-mangling-version=v0
-
-pub(crate) struct Foo<'a, I, E>(I, &'a E);
-
-impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
-where
-    I: Iterator<Item = &'a (T, E)>,
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.find(|_| true)
-    }
-}
-
-fn main() {
-    let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
-    let mut b = Foo([(1u16, 1u32)].iter(), &1u32);
-    let _ = a.next();
-    let _ = b.next();
-}
diff --git a/tests/ui/polymorphization/too-many-generic-params.rs b/tests/ui/polymorphization/too-many-generic-params.rs
deleted file mode 100644
index db160c336e0..00000000000
--- a/tests/ui/polymorphization/too-many-generic-params.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-//@ build-pass
-#![feature(rustc_attrs)]
-
-// This test checks that the analysis doesn't panic when there are >64 generic parameters, but
-// instead considers those parameters used.
-
-#[rustc_polymorphize_error]
-fn bar<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA,
-       AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW,
-       AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM>()
-{
-    let _: Option<A> = None;
-    let _: Option<B> = None;
-    let _: Option<C> = None;
-    let _: Option<D> = None;
-    let _: Option<E> = None;
-    let _: Option<F> = None;
-    let _: Option<G> = None;
-    let _: Option<H> = None;
-    let _: Option<I> = None;
-    let _: Option<J> = None;
-    let _: Option<K> = None;
-    let _: Option<L> = None;
-    let _: Option<M> = None;
-    let _: Option<N> = None;
-    let _: Option<O> = None;
-    let _: Option<P> = None;
-    let _: Option<Q> = None;
-    let _: Option<R> = None;
-    let _: Option<S> = None;
-    let _: Option<T> = None;
-    let _: Option<U> = None;
-    let _: Option<V> = None;
-    let _: Option<W> = None;
-    let _: Option<X> = None;
-    let _: Option<Y> = None;
-    let _: Option<Z> = None;
-    let _: Option<AA> = None;
-    let _: Option<AB> = None;
-    let _: Option<AC> = None;
-    let _: Option<AD> = None;
-    let _: Option<AE> = None;
-    let _: Option<AF> = None;
-    let _: Option<AG> = None;
-    let _: Option<AH> = None;
-    let _: Option<AI> = None;
-    let _: Option<AJ> = None;
-    let _: Option<AK> = None;
-    let _: Option<AL> = None;
-    let _: Option<AM> = None;
-    let _: Option<AN> = None;
-    let _: Option<AO> = None;
-    let _: Option<AP> = None;
-    let _: Option<AQ> = None;
-    let _: Option<AR> = None;
-    let _: Option<AS> = None;
-    let _: Option<AT> = None;
-    let _: Option<AU> = None;
-    let _: Option<AV> = None;
-    let _: Option<AW> = None;
-    let _: Option<AX> = None;
-    let _: Option<AY> = None;
-    let _: Option<AZ> = None;
-    let _: Option<BA> = None;
-    let _: Option<BB> = None;
-    let _: Option<BC> = None;
-    let _: Option<BD> = None;
-    let _: Option<BE> = None;
-    let _: Option<BF> = None;
-    let _: Option<BG> = None;
-    let _: Option<BH> = None;
-    let _: Option<BI> = None;
-    let _: Option<BJ> = None;
-    let _: Option<BK> = None;
-    let _: Option<BL> = None;
-    let _: Option<BM> = None;
-}
-
-fn main() {
-    bar::<u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
-          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
-          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
-          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
-          u32>();
-}
diff --git a/tests/ui/polymorphization/type_parameters/closures.rs b/tests/ui/polymorphization/type_parameters/closures.rs
deleted file mode 100644
index 552c5cb8980..00000000000
--- a/tests/ui/polymorphization/type_parameters/closures.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(stmt_expr_attributes, rustc_attrs)]
-
-// This test checks that the polymorphization analysis correctly detects unused type
-// parameters in closures.
-
-// Function doesn't have any generic parameters to be unused.
-#[rustc_polymorphize_error]
-pub fn no_parameters() {
-    let _ = || {};
-}
-
-// Function has an unused generic parameter in parent and closure.
-#[rustc_polymorphize_error]
-pub fn unused<T>() -> u32 {
-    //~^ ERROR item has unused generic parameters
-
-    let add_one = |x: u32| x + 1;
-    //~^ ERROR item has unused generic parameters
-    add_one(3)
-}
-
-// Function has an unused generic parameter in closure, but not in parent.
-#[rustc_polymorphize_error]
-pub fn used_parent<T: Default>() -> u32 {
-    let _: T = Default::default();
-    let add_one = |x: u32| x + 1;
-    //~^ ERROR item has unused generic parameters
-    add_one(3)
-}
-
-// Function uses generic parameter in value of a binding in closure.
-#[rustc_polymorphize_error]
-pub fn used_binding_value<T: Default>() -> T {
-    let x = || {
-        let y: T = Default::default();
-        y
-    };
-
-    x()
-}
-
-// Function uses generic parameter in generic of a binding in closure.
-#[rustc_polymorphize_error]
-pub fn used_binding_generic<T>() -> Option<T> {
-    let x = || {
-        let y: Option<T> = None;
-        y
-    };
-
-    x()
-}
-
-// Function and closure uses generic parameter in argument.
-#[rustc_polymorphize_error]
-pub fn used_argument<T>(t: T) -> u32 {
-    let x = |_: T| 3;
-    x(t)
-}
-
-// Closure uses generic parameter in argument.
-#[rustc_polymorphize_error]
-pub fn used_argument_closure<T: Default>() -> u32 {
-    let t: T = Default::default();
-
-    let x = |_: T| 3;
-    x(t)
-}
-
-// Closure uses generic parameter as upvar.
-#[rustc_polymorphize_error]
-pub fn used_upvar<T: Default>() -> T {
-    let x: T = Default::default();
-
-    let y = || x;
-    y()
-}
-
-// Closure uses generic parameter in substitutions to another function.
-#[rustc_polymorphize_error]
-pub fn used_substs<T>() -> u32 {
-    let x = || unused::<T>();
-    x()
-}
-
-struct Foo<F>(F);
-
-impl<F: Default> Foo<F> {
-    // Function has an unused generic parameter from impl and fn.
-    #[rustc_polymorphize_error]
-    pub fn unused_all<G: Default>() -> u32 {
-        //~^ ERROR item has unused generic parameters
-        let add_one = |x: u32| x + 1;
-        //~^ ERROR item has unused generic parameters
-        add_one(3)
-    }
-
-    // Function uses generic parameter from impl and fn in closure.
-    #[rustc_polymorphize_error]
-    pub fn used_both<G: Default>() -> u32 {
-        let add_one = |x: u32| {
-            let _: F = Default::default();
-            let _: G = Default::default();
-            x + 1
-        };
-
-        add_one(3)
-    }
-
-    // Function uses generic parameter from fn in closure.
-    #[rustc_polymorphize_error]
-    pub fn used_fn<G: Default>() -> u32 {
-        //~^ ERROR item has unused generic parameters
-        let add_one = |x: u32| {
-            //~^ ERROR item has unused generic parameters
-            let _: G = Default::default();
-            x + 1
-        };
-
-        add_one(3)
-    }
-
-    // Function uses generic parameter from impl in closure.
-    #[rustc_polymorphize_error]
-    pub fn used_impl<G: Default>() -> u32 {
-        //~^ ERROR item has unused generic parameters
-        let add_one = |x: u32| {
-            //~^ ERROR item has unused generic parameters
-            let _: F = Default::default();
-            x + 1
-        };
-
-        add_one(3)
-    }
-
-    // Closure uses generic parameter in substitutions to another function.
-    #[rustc_polymorphize_error]
-    pub fn used_substs() -> u32 {
-        let x = || unused::<F>();
-        x()
-    }
-}
-
-fn main() {
-    no_parameters();
-    let _ = unused::<u32>();
-    let _ = used_parent::<u32>();
-    let _ = used_binding_value::<u32>();
-    let _ = used_binding_generic::<u32>();
-    let _ = used_argument(3u32);
-    let _ = used_argument_closure::<u32>();
-    let _ = used_upvar::<u32>();
-    let _ = used_substs::<u32>();
-
-    let _ = Foo::<u32>::unused_all::<u32>();
-    let _ = Foo::<u32>::used_both::<u32>();
-    let _ = Foo::<u32>::used_impl::<u32>();
-    let _ = Foo::<u32>::used_fn::<u32>();
-    let _ = Foo::<u32>::used_substs();
-}
diff --git a/tests/ui/polymorphization/type_parameters/closures.stderr b/tests/ui/polymorphization/type_parameters/closures.stderr
deleted file mode 100644
index 5c3b46c6041..00000000000
--- a/tests/ui/polymorphization/type_parameters/closures.stderr
+++ /dev/null
@@ -1,80 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/closures.rs:19:19
-   |
-LL | pub fn unused<T>() -> u32 {
-   |               - generic parameter `T` is unused
-...
-LL |     let add_one = |x: u32| x + 1;
-   |                   ^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:16:8
-   |
-LL | pub fn unused<T>() -> u32 {
-   |        ^^^^^^ - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:28:19
-   |
-LL | pub fn used_parent<T: Default>() -> u32 {
-   |                    - generic parameter `T` is unused
-LL |     let _: T = Default::default();
-LL |     let add_one = |x: u32| x + 1;
-   |                   ^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:94:23
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn unused_all<G: Default>() -> u32 {
-   |                       - generic parameter `G` is unused
-LL |
-LL |         let add_one = |x: u32| x + 1;
-   |                       ^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:92:12
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn unused_all<G: Default>() -> u32 {
-   |            ^^^^^^^^^^ - generic parameter `G` is unused
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:115:23
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |         let add_one = |x: u32| {
-   |                       ^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:113:12
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn used_fn<G: Default>() -> u32 {
-   |            ^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:128:23
-   |
-LL |     pub fn used_impl<G: Default>() -> u32 {
-   |                      - generic parameter `G` is unused
-LL |
-LL |         let add_one = |x: u32| {
-   |                       ^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/closures.rs:126:12
-   |
-LL |     pub fn used_impl<G: Default>() -> u32 {
-   |            ^^^^^^^^^ - generic parameter `G` is unused
-
-error: aborting due to 9 previous errors
-
diff --git a/tests/ui/polymorphization/type_parameters/functions.rs b/tests/ui/polymorphization/type_parameters/functions.rs
deleted file mode 100644
index 548993fbca9..00000000000
--- a/tests/ui/polymorphization/type_parameters/functions.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(rustc_attrs)]
-
-// This test checks that the polymorphization analysis correctly detects unused type
-// parameters in functions.
-
-// Function doesn't have any generic parameters to be unused.
-#[rustc_polymorphize_error]
-pub fn no_parameters() {}
-
-// Function has an unused generic parameter.
-#[rustc_polymorphize_error]
-pub fn unused<T>() {
-    //~^ ERROR item has unused generic parameters
-}
-
-// Function uses generic parameter in value of a binding.
-#[rustc_polymorphize_error]
-pub fn used_binding_value<T: Default>() {
-    let _: T = Default::default();
-}
-
-// Function uses generic parameter in generic of a binding.
-#[rustc_polymorphize_error]
-pub fn used_binding_generic<T>() {
-    let _: Option<T> = None;
-}
-
-// Function uses generic parameter in argument.
-#[rustc_polymorphize_error]
-pub fn used_argument<T>(_: T) {}
-
-// Function uses generic parameter in substitutions to another function.
-#[rustc_polymorphize_error]
-pub fn used_substs<T>() {
-    unused::<T>()
-}
-
-struct Foo<F>(F);
-
-impl<F: Default> Foo<F> {
-    // Function has an unused generic parameter from impl.
-    #[rustc_polymorphize_error]
-    pub fn unused_impl() {
-        //~^ ERROR item has unused generic parameters
-    }
-
-    // Function has an unused generic parameter from impl and fn.
-    #[rustc_polymorphize_error]
-    pub fn unused_both<G: Default>() {
-        //~^ ERROR item has unused generic parameters
-    }
-
-    // Function uses generic parameter from impl.
-    #[rustc_polymorphize_error]
-    pub fn used_impl() {
-        let _: F = Default::default();
-    }
-
-    // Function uses generic parameter from impl.
-    #[rustc_polymorphize_error]
-    pub fn used_fn<G: Default>() {
-        //~^ ERROR item has unused generic parameters
-        let _: G = Default::default();
-    }
-
-    // Function uses generic parameter from impl.
-    #[rustc_polymorphize_error]
-    pub fn used_both<G: Default>() {
-        let _: F = Default::default();
-        let _: G = Default::default();
-    }
-
-    // Function uses generic parameter in substitutions to another function.
-    #[rustc_polymorphize_error]
-    pub fn used_substs() {
-        unused::<F>()
-    }
-}
-
-fn main() {
-    no_parameters();
-    unused::<u32>();
-    used_binding_value::<u32>();
-    used_binding_generic::<u32>();
-    used_argument(3u32);
-    used_substs::<u32>();
-
-    Foo::<u32>::unused_impl();
-    Foo::<u32>::unused_both::<u32>();
-    Foo::<u32>::used_impl();
-    Foo::<u32>::used_fn::<u32>();
-    Foo::<u32>::used_both::<u32>();
-    Foo::<u32>::used_substs();
-}
diff --git a/tests/ui/polymorphization/type_parameters/functions.stderr b/tests/ui/polymorphization/type_parameters/functions.stderr
deleted file mode 100644
index d629ff7bb4d..00000000000
--- a/tests/ui/polymorphization/type_parameters/functions.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/functions.rs:14:8
-   |
-LL | pub fn unused<T>() {
-   |        ^^^^^^ - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/functions.rs:45:12
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn unused_impl() {
-   |            ^^^^^^^^^^^
-
-error: item has unused generic parameters
-  --> $DIR/functions.rs:51:12
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn unused_both<G: Default>() {
-   |            ^^^^^^^^^^^ - generic parameter `G` is unused
-
-error: item has unused generic parameters
-  --> $DIR/functions.rs:63:12
-   |
-LL | impl<F: Default> Foo<F> {
-   |      - generic parameter `F` is unused
-...
-LL |     pub fn used_fn<G: Default>() {
-   |            ^^^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/polymorphization/unsized_cast.rs b/tests/ui/polymorphization/unsized_cast.rs
deleted file mode 100644
index 749e21f4e5b..00000000000
--- a/tests/ui/polymorphization/unsized_cast.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ build-fail
-//@ compile-flags:-Zpolymorphize=on
-#![feature(fn_traits, rustc_attrs, unboxed_closures)]
-
-// This test checks that the polymorphization analysis considers a closure
-// as using all generic parameters if it does an unsizing cast.
-
-#[rustc_polymorphize_error]
-fn foo<T: Default>() {
-    let _: T = Default::default();
-    (|| Box::new(|| {}) as Box<dyn Fn()>)();
-    //~^ ERROR item has unused generic parameters
-    //~^^ ERROR item has unused generic parameters
-}
-
-#[rustc_polymorphize_error]
-fn foo2<T: Default>() {
-    let _: T = Default::default();
-    (|| {
-        //~^ ERROR item has unused generic parameters
-        let call: extern "rust-call" fn(_, _) = Fn::call;
-        call(&|| {}, ());
-        //~^ ERROR item has unused generic parameters
-    })();
-}
-
-fn main() {
-    foo::<u32>();
-    foo2::<u32>();
-}
diff --git a/tests/ui/polymorphization/unsized_cast.stderr b/tests/ui/polymorphization/unsized_cast.stderr
deleted file mode 100644
index 27f88d28174..00000000000
--- a/tests/ui/polymorphization/unsized_cast.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: item has unused generic parameters
-  --> $DIR/unsized_cast.rs:11:18
-   |
-LL | fn foo<T: Default>() {
-   |        - generic parameter `T` is unused
-LL |     let _: T = Default::default();
-LL |     (|| Box::new(|| {}) as Box<dyn Fn()>)();
-   |                  ^^
-
-error: item has unused generic parameters
-  --> $DIR/unsized_cast.rs:11:6
-   |
-LL | fn foo<T: Default>() {
-   |        - generic parameter `T` is unused
-LL |     let _: T = Default::default();
-LL |     (|| Box::new(|| {}) as Box<dyn Fn()>)();
-   |      ^^
-
-error: item has unused generic parameters
-  --> $DIR/unsized_cast.rs:22:15
-   |
-LL | fn foo2<T: Default>() {
-   |         - generic parameter `T` is unused
-...
-LL |         call(&|| {}, ());
-   |               ^^
-
-error: item has unused generic parameters
-  --> $DIR/unsized_cast.rs:19:6
-   |
-LL | fn foo2<T: Default>() {
-   |         - generic parameter `T` is unused
-LL |     let _: T = Default::default();
-LL |     (|| {
-   |      ^^
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
index 5c6eef46103..7b7b1a9580b 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
@@ -1,5 +1,5 @@
 // `S` is infinitely recursing so it's not possible to generate a finite
-// drop impl (ignoring polymorphization).
+// drop impl.
 //
 // Dropck should therefore detect that this is the case and eagerly error.
 
diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
index b17d1e0ab11..87f0f47f240 100644
--- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
+++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
 LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait2`
    |
 LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
    |                    ++++++++++++++++++++++++
@@ -17,7 +17,7 @@ LL | |
 LL | | }
    | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait2`
    |
 LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
    |                    ++++++++++++++++++++++++
diff --git a/tests/ui/resolve/issue-55673.stderr b/tests/ui/resolve/issue-55673.stderr
index 4069b35a998..7d420126199 100644
--- a/tests/ui/resolve/issue-55673.stderr
+++ b/tests/ui/resolve/issue-55673.stderr
@@ -15,7 +15,7 @@ error[E0220]: associated type `Baa` not found for `T`
 LL |     T::Baa: std::fmt::Debug,
    |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
    |
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Foo`
    |
 LL |     T::Baa: std::fmt::Debug, T: Foo
    |                            ~~~~~~~~
diff --git a/tests/ui/sanitizer/cfi/coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs
index ec7c5888968..3ad896afd00 100644
--- a/tests/ui/sanitizer/cfi/coroutine.rs
+++ b/tests/ui/sanitizer/cfi/coroutine.rs
@@ -16,7 +16,6 @@
 
 #![feature(coroutines, stmt_expr_attributes)]
 #![feature(coroutine_trait)]
-#![feature(noop_waker)]
 #![feature(gen_blocks)]
 #![feature(async_iterator)]
 
diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr
index afdbe2eb226..57d67ac526a 100644
--- a/tests/ui/specialization/default-generic-associated-type-bound.stderr
+++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr
@@ -20,7 +20,7 @@ note: required by a bound in `X::U`
    |
 LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
    |                 ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `PartialEq`
    |
 LL | impl<T: 'static + std::cmp::PartialEq> X for T {
    |                 +++++++++++++++++++++
diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
index 01188e293bd..4a51a7dfa47 100644
--- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -19,7 +19,7 @@ note: required by a bound in `Foo`
    |
 LL | trait Foo<'a, T: Eq + 'a> { }
    |                  ^^ required by this bound in `Foo`
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Eq`
    |
 LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {}
    |               ++++++++++++++
diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr
index 2c20077078f..29a82a4d875 100644
--- a/tests/ui/specialization/issue-33017.stderr
+++ b/tests/ui/specialization/issue-33017.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `UncheckedCopy::Output`
    |
 LL |     type Output: From<Self> + Copy + Into<Self>;
    |                               ^^^^ required by this bound in `UncheckedCopy::Output`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> UncheckedCopy for T {
    |       +++++++++++++++++++
diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr
index 268fc3a9591..84e526f4597 100644
--- a/tests/ui/specialization/min_specialization/issue-79224.stderr
+++ b/tests/ui/specialization/min_specialization/issue-79224.stderr
@@ -5,7 +5,7 @@ LL | impl<B: ?Sized> Display for Cow<'_, B> {
    |                             ^^^^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
-help: consider further restricting this bound
+help: consider further restricting type parameter `B` with trait `Clone`
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
@@ -17,7 +17,7 @@ LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
-help: consider further restricting this bound
+help: consider further restricting type parameter `B` with trait `Clone`
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
@@ -29,7 +29,7 @@ LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    |             ^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
-help: consider further restricting this bound
+help: consider further restricting type parameter `B` with trait `Clone`
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
@@ -47,7 +47,7 @@ LL | |     }
    | |_____^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
-help: consider further restricting this bound
+help: consider further restricting type parameter `B` with trait `Clone`
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr
index 69e9af72647..6732033e774 100644
--- a/tests/ui/suggestions/assoc-const-as-fn.stderr
+++ b/tests/ui/suggestions/assoc-const-as-fn.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied
 LL |     <T as GlUniformScalar>::FACTORY(1, value);
    |      ^ the trait `GlUniformScalar` is not implemented for `T`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `GlUniformScalar`
    |
 LL | pub fn foo<T: UniformScalar + GlUniformScalar>(value: T) {
    |                             +++++++++++++++++
diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr
index 4965e7439f8..e30deb11398 100644
--- a/tests/ui/suggestions/bound-suggestions.stderr
+++ b/tests/ui/suggestions/bound-suggestions.stderr
@@ -5,7 +5,7 @@ LL |     println!("{:?}", t);
    |                      ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider restricting opaque type `impl Sized` with trait `Debug`
    |
 LL | fn test_impl(t: impl Sized + std::fmt::Debug) {
    |                            +++++++++++++++++
@@ -17,7 +17,7 @@ LL |     println!("{:?}", t);
    |                      ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Debug`
    |
 LL | fn test_no_bounds<T: std::fmt::Debug>(t: T) {
    |                    +++++++++++++++++
@@ -29,7 +29,7 @@ LL |     println!("{:?}", t);
    |                      ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Debug`
    |
 LL | fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) {
    |                            +++++++++++++++++
@@ -41,7 +41,7 @@ LL |     println!("{:?} {:?}", x, y);
    |                              ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting type parameter `Y`
+help: consider further restricting type parameter `Y` with trait `Debug`
    |
 LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug {
    |                                                                   ~~~~~~~~~~~~~~~~~~~~
@@ -53,7 +53,7 @@ LL |     println!("{:?}", x);
    |                      ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `X` with trait `Debug`
    |
 LL | fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug {
    |                                                 +++++++++++++++++
@@ -65,7 +65,7 @@ LL |     println!("{:?}", x);
    |                      ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `X` with trait `Debug`
    |
 LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized {
    |                                                   +++++++++++++++++
diff --git a/tests/ui/suggestions/clone-bounds-121524.rs b/tests/ui/suggestions/clone-bounds-121524.rs
index 8cd60b452de..b7760584ebb 100644
--- a/tests/ui/suggestions/clone-bounds-121524.rs
+++ b/tests/ui/suggestions/clone-bounds-121524.rs
@@ -6,7 +6,7 @@ trait DoesAThing {}
 impl DoesAThing for ThingThatDoesAThing {}
 
 fn clones_impl_ref_inline(thing: &impl DoesAThing) {
-    //~^ HELP consider further restricting this bound
+    //~^ HELP consider restricting opaque type `impl DoesAThing` with trait `Clone`
     drops_impl_owned(thing.clone()); //~ ERROR E0277
     //~^ NOTE copies the reference
     //~| NOTE the trait `DoesAThing` is not implemented for `&impl DoesAThing`
diff --git a/tests/ui/suggestions/clone-bounds-121524.stderr b/tests/ui/suggestions/clone-bounds-121524.stderr
index 6d60508a4a1..bdba8d7e472 100644
--- a/tests/ui/suggestions/clone-bounds-121524.stderr
+++ b/tests/ui/suggestions/clone-bounds-121524.stderr
@@ -9,7 +9,7 @@ note: this `clone()` copies the reference, which does not do anything, because `
    |
 LL |     drops_impl_owned(thing.clone());
    |                            ^^^^^
-help: consider further restricting this bound
+help: consider restricting opaque type `impl DoesAThing` with trait `Clone`
    |
 LL | fn clones_impl_ref_inline(thing: &impl DoesAThing + Clone) {
    |                                                   +++++++
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
index afbb9c32d51..03a14b03781 100644
--- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -15,7 +15,7 @@ note: `T` does not implement `Clone`, so `&T` was cloned instead
    |
 LL |     t.clone()
    |     ^
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL | fn wat<T: Clone>(t: &T) -> T {
    |         +++++++
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
index 680890e880c..eae0b0ae817 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.stderr
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -14,7 +14,7 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
 note: required by a bound in `Eq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL | pub struct Struct<T: std::clone::Clone>(T);
    |                    +++++++++++++++++++
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
index bffcb1af487..37a5f4932ff 100644
--- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -38,7 +38,7 @@ LL |     impl<T: Debug + Trait> Debug for Inner<T> {
    = note: required for `&c::Inner<T>` to implement `Debug`
    = note: required for the cast from `&&c::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL |     struct Outer<T: c::Trait>(Inner<T>);
    |                   ++++++++++
@@ -60,7 +60,7 @@ LL |     impl<T> Debug for Inner<T> where T: Debug, T: Trait {
    = note: required for `&d::Inner<T>` to implement `Debug`
    = note: required for the cast from `&&d::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL |     struct Outer<T: d::Trait>(Inner<T>);
    |                   ++++++++++
@@ -82,7 +82,7 @@ LL |     impl<T> Debug for Inner<T> where T: Debug + Trait {
    = note: required for `&e::Inner<T>` to implement `Debug`
    = note: required for the cast from `&&e::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL |     struct Outer<T: e::Trait>(Inner<T>);
    |                   ++++++++++
@@ -104,7 +104,7 @@ LL |     impl<T: Debug> Debug for Inner<T> where T: Trait {
    = note: required for `&f::Inner<T>` to implement `Debug`
    = note: required for the cast from `&&f::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL |     struct Outer<T: f::Trait>(Inner<T>);
    |                   ++++++++++
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
index 8607917ede6..8b1c0b9a77a 100644
--- a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `&T: X` is not satisfied
 LL |     foo(s);
    |         ^ the trait `X` is not implemented for `&T`
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Clone`
    |
 LL | fn bar<T: X + Clone>(s: &T) {
    |             +++++++
diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr
index 0e95167d851..7fe091ef71c 100644
--- a/tests/ui/suggestions/issue-97677.stderr
+++ b/tests/ui/suggestions/issue-97677.stderr
@@ -6,7 +6,7 @@ LL |     n + 10
    |     |
    |     N
    |
-help: consider restricting type parameter `N`
+help: consider restricting type parameter `N` with trait `Add`
    |
 LL | fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N {
    |             ++++++++++++++++++++++++++++++++
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
index d65ad109241..4408fe0a0a4 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Vector2`
    |
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ^^^^ required by this bound in `Vector2`
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: Debug + std::marker::Copy> {
    |                          +++++++++++++++++++
@@ -32,7 +32,7 @@ LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ---- unsatisfied trait bound introduced in this `derive` macro
    = note: required for the cast from `&Vector2<K>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: Debug + std::marker::Copy> {
    |                          +++++++++++++++++++
@@ -52,7 +52,7 @@ note: required by a bound in `Vector2`
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ^^^^ required by this bound in `Vector2`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: Debug + std::marker::Copy> {
    |                          +++++++++++++++++++
@@ -74,7 +74,7 @@ LL | #[derive(Debug, Copy, Clone)]
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ---- unsatisfied trait bound introduced in this `derive` macro
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: Debug + std::marker::Copy> {
    |                          +++++++++++++++++++
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
index 2ade0e974e4..1bbf6f66ab2 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
@@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
 LL |     pub loc: Vector2<K>,
    |              ^^^^^^^^^^
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: Copy + Debug>{
    |                         +++++++
@@ -29,7 +29,7 @@ note: required by a bound in `Vector2`
    |
 LL | pub struct Vector2<T: Debug + Copy + Clone>{
    |                       ^^^^^ required by this bound in `Vector2`
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: Copy + std::fmt::Debug>{
    |                         +++++++++++++++++
@@ -44,7 +44,7 @@ LL |     pub loc: Vector2<K>,
    |     ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: Copy + std::fmt::Debug>{
    |                         +++++++++++++++++
@@ -59,7 +59,7 @@ LL |     pub size: Vector2<K>
    |     ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting this bound
+help: consider further restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: Copy + std::fmt::Debug>{
    |                         +++++++++++++++++
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
index 316c2fa0fc9..8b5cced4c4a 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
@@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
 LL |     pub loc: Vector2<K>,
    |              ^^^^^^^^^^
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: Debug> {
    |                  +++++++
@@ -29,7 +29,7 @@ note: required by a bound in `Vector2`
    |
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                       ^^^^^ required by this bound in `Vector2`
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: std::fmt::Debug> {
    |                  +++++++++++++++++
@@ -45,7 +45,7 @@ note: required by a bound in `Vector2`
    |
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ^^^^ required by this bound in `Vector2`
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: std::marker::Copy> {
    |                  +++++++++++++++++++
@@ -68,7 +68,7 @@ LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ---- unsatisfied trait bound introduced in this `derive` macro
    = note: required for the cast from `&Vector2<K>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: std::marker::Copy> {
    |                  +++++++++++++++++++
@@ -83,7 +83,7 @@ LL |     pub loc: Vector2<K>,
    |     ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: std::fmt::Debug> {
    |                  +++++++++++++++++
@@ -103,7 +103,7 @@ note: required by a bound in `Vector2`
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ^^^^ required by this bound in `Vector2`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: std::marker::Copy> {
    |                  +++++++++++++++++++
@@ -118,7 +118,7 @@ LL |     pub size: Vector2<K>,
    |     ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Debug`
    |
 LL | pub struct AABB<K: std::fmt::Debug> {
    |                  +++++++++++++++++
@@ -140,7 +140,7 @@ LL | #[derive(Debug, Copy, Clone)]
 LL | pub struct Vector2<T: Debug + Copy + Clone> {
    |                               ---- unsatisfied trait bound introduced in this `derive` macro
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Copy`
    |
 LL | pub struct AABB<K: std::marker::Copy> {
    |                  +++++++++++++++++++
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
index 23a75154f20..600e5ae63d3 100644
--- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
@@ -12,7 +12,7 @@ note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Dis
    |
 LL | struct Wrapper<T>(T);
    |                   ^
-help: consider restricting type parameter `S`
+help: consider restricting type parameter `S` with trait `Display`
    |
 LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
    |       +++++++++++++++++++
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
index c9f277fb350..b22aa35ef6d 100644
--- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
@@ -7,7 +7,7 @@ LL |
 LL | impl<S> Copy for Wrapper<S> {}
    |                  ^^^^^^^^^^
    |
-help: consider restricting type parameter `S`
+help: consider restricting type parameter `S` with trait `Copy`
    |
 LL | impl<S: Copy> Copy for Wrapper<S> {}
    |       ++++++
diff --git a/tests/ui/suggestions/restrict-type-argument.stderr b/tests/ui/suggestions/restrict-type-argument.stderr
index 01c2de79864..4b6da8a9cd9 100644
--- a/tests/ui/suggestions/restrict-type-argument.stderr
+++ b/tests/ui/suggestions/restrict-type-argument.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider further restricting this bound
+help: consider restricting opaque type `impl Sync` with trait `Send`
    |
 LL | fn use_impl_sync(val: impl Sync + std::marker::Send) {
    |                                 +++++++++++++++++++
@@ -29,7 +29,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider further restricting this bound
+help: consider further restricting type parameter `S` with trait `Send`
    |
 LL | fn use_where<S>(val: S) where S: Sync + std::marker::Send {
    |                                       +++++++++++++++++++
@@ -47,7 +47,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider further restricting this bound
+help: consider further restricting type parameter `S` with trait `Send`
    |
 LL | fn use_bound<S: Sync + std::marker::Send>(val: S) {
    |                      +++++++++++++++++++
@@ -65,7 +65,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider further restricting this bound
+help: consider further restricting type parameter `S` with trait `Send`
    |
 LL |     Sync + std::marker::Send
    |          +++++++++++++++++++
@@ -83,7 +83,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider further restricting this bound
+help: consider further restricting type parameter `S` with trait `Send`
    |
 LL | fn use_bound_and_where<S: Sync + std::marker::Send>(val: S) where S: std::fmt::Debug {
    |                                +++++++++++++++++++
@@ -101,7 +101,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T: Send>(val: T) {}
    |               ^^^^ required by this bound in `is_send`
-help: consider restricting type parameter `S`
+help: consider restricting type parameter `S` with trait `Send`
    |
 LL | fn use_unbound<S: std::marker::Send>(val: S) {
    |                 +++++++++++++++++++
diff --git a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr
index 6a75cbdf639..346d19f1b77 100644
--- a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ConstrainedStruct`
    |
 LL | struct ConstrainedStruct<X: Copy> {
    |                             ^^^^ required by this bound in `ConstrainedStruct`
-help: consider further restricting type parameter `X`
+help: consider further restricting type parameter `X` with trait `Copy`
    |
 LL | trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy {
    |                                                               ++++++++++++++++++++++
@@ -25,7 +25,7 @@ note: required by a bound in `ConstrainedStruct`
    |
 LL | struct ConstrainedStruct<X: Copy> {
    |                             ^^^^ required by this bound in `ConstrainedStruct`
-help: consider further restricting type parameter `X`
+help: consider further restricting type parameter `X` with trait `Copy`
    |
 LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy {
    |                                                                             ++++++++++++++++++++++
@@ -41,7 +41,7 @@ note: required by a bound in `ConstrainedStruct`
    |
 LL | struct ConstrainedStruct<X: Copy> {
    |                             ^^^^ required by this bound in `ConstrainedStruct`
-help: consider further restricting type parameter `X`
+help: consider further restricting type parameter `X` with trait `Copy`
    |
 LL | trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy {
    |                                                               ++++++++++++++++++++++
@@ -57,7 +57,7 @@ note: required by a bound in `ConstrainedStruct`
    |
 LL | struct ConstrainedStruct<X: Copy> {
    |                             ^^^^ required by this bound in `ConstrainedStruct`
-help: consider further restricting type parameter `X`
+help: consider further restricting type parameter `X` with trait `Copy`
    |
 LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy {
    |                                                                             ++++++++++++++++++++++
diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.rs b/tests/ui/trait-bounds/unstable-trait-suggestion.rs
new file mode 100644
index 00000000000..ba96b4f3f97
--- /dev/null
+++ b/tests/ui/trait-bounds/unstable-trait-suggestion.rs
@@ -0,0 +1,19 @@
+#![feature(staged_api)]
+#![allow(internal_features)]
+#![stable(feature = "unit_test", since = "1.0.0")]
+
+#[unstable(feature = "step_trait", issue = "42168")]
+pub trait Unstable {}
+
+#[stable(feature = "unit_test", since = "1.0.0")]
+fn foo<T: Unstable>(_: T) {}
+
+#[stable(feature = "unit_test", since = "1.0.0")]
+pub fn bar<T>(t: T) { //~ HELP consider restricting type parameter `T` with unstable trait `Unstable`
+    foo(t) //~ ERROR E0277
+}
+#[stable(feature = "unit_test", since = "1.0.0")]
+pub fn baz<T>(t: std::ops::Range<T>) { //~ HELP consider restricting type parameter `T` with unstable trait
+    for _ in t {} //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr
new file mode 100644
index 00000000000..dfa47f2ab46
--- /dev/null
+++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the trait bound `T: Unstable` is not satisfied
+  --> $DIR/unstable-trait-suggestion.rs:13:9
+   |
+LL |     foo(t)
+   |     --- ^ the trait `Unstable` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/unstable-trait-suggestion.rs:9:11
+   |
+LL | fn foo<T: Unstable>(_: T) {}
+   |           ^^^^^^^^ required by this bound in `foo`
+help: consider restricting type parameter `T` with unstable trait `Unstable`
+   |
+LL | pub fn bar<T: Unstable>(t: T) {
+   |             ++++++++++
+
+error[E0277]: the trait bound `T: Step` is not satisfied
+  --> $DIR/unstable-trait-suggestion.rs:17:14
+   |
+LL |     for _ in t {}
+   |              ^ the trait `Step` is not implemented for `T`
+   |
+   = note: required for `std::ops::Range<T>` to implement `Iterator`
+   = note: required for `std::ops::Range<T>` to implement `IntoIterator`
+help: consider restricting type parameter `T` with unstable trait `Step`
+   |
+LL | pub fn baz<T: std::iter::Step>(t: std::ops::Range<T>) {
+   |             +++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr
index 3be6e8a49d6..42b0104e865 100644
--- a/tests/ui/traits/alias/wf.stderr
+++ b/tests/ui/traits/alias/wf.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `A`
    |
 LL | trait A<T: Foo> {}
    |            ^^^ required by this bound in `A`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Foo`
    |
 LL | trait B<T: Foo> = A<T>;
    |          +++++
diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr
index 376a83e58a7..3b3d6e5f832 100644
--- a/tests/ui/traits/bad-method-typaram-kind.stderr
+++ b/tests/ui/traits/bad-method-typaram-kind.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `Bar::bar`
    |
 LL |     fn bar<T:Send>(&self);
    |              ^^^^ required by this bound in `Bar::bar`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Send`
    |
 LL | fn foo<T:'static + std::marker::Send>() {
    |                  +++++++++++++++++++
diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr
index 606f764852f..7d6420c6482 100644
--- a/tests/ui/traits/bound/on-structs-and-enums.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Foo`
    |
 LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | impl<T: Trait> Foo<T> {
    |       +++++++
@@ -59,7 +59,7 @@ note: required by a bound in `Foo`
    |
 LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Trait`
    |
 LL | struct Badness<U: Trait> {
    |                 +++++++
@@ -75,7 +75,7 @@ note: required by a bound in `Bar`
    |
 LL | enum Bar<T:Trait> {
    |            ^^^^^ required by this bound in `Bar`
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `Trait`
    |
 LL | enum MoreBadness<V: Trait> {
    |                   +++++++
diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr
index 9a53c61d019..21fb19daad4 100644
--- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr
@@ -42,10 +42,6 @@ LL |     *t == *t
    |     ^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                          ++++++++++++++++++++++++++++
 
 error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions
   --> $DIR/call-generic-method-chain.rs:16:15
diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
index a168171cfe8..845949a38bf 100644
--- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
@@ -42,10 +42,6 @@ LL |     *t == *t
    |     ^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn equals_self<T: PartialEq + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                                      ++++++++++++++++++++++++++++
 
 error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions
   --> $DIR/call-generic-method-dup-bound.rs:14:15
@@ -62,10 +58,6 @@ LL |     *t == *t
    |     ^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn equals_self2<T: A + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                               ++++++++++++++++++++++++++++
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr
index 07e50a7f7da..6bacb986fef 100644
--- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr
@@ -5,10 +5,6 @@ LL |     *t == *t
    |     ^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                       ++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr
index af6e6d25dc9..0c0037e36b8 100644
--- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr
@@ -28,10 +28,6 @@ LL |     *t == *t
    |     ^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                          ++++++++++++++++++++++++++++
 
 error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions
   --> $DIR/call-generic-method-pass.rs:16:15
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
index cb4c994bc2f..a76dc3e82af 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
+++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
@@ -19,10 +19,6 @@ LL |     x(())
    |     ^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 {
-   |                                                         +++++++++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr
index 43af435ae64..d37ff3d727c 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr
+++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr
@@ -19,10 +19,6 @@ LL |     x(())
    |     ^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 {
-   |                                                         +++++++++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr
index 2e9e37ba321..8ceaae16d8e 100644
--- a/tests/ui/traits/const-traits/const-closures.stderr
+++ b/tests/ui/traits/const-traits/const-closures.stderr
@@ -61,10 +61,6 @@ LL |     f() + f()
    |     ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 {
-   |                                      +++++++++++++
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/const-closures.rs:24:11
@@ -73,10 +69,6 @@ LL |     f() + f()
    |           ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 {
-   |                                      +++++++++++++
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/const-closures.rs:12:5
@@ -85,10 +77,6 @@ LL |     f() * 7
    |     ^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL |         F: ~const FnOnce() -> u8 + ~const Fn(),
-   |                                  +++++++++++++
 
 error: aborting due to 11 previous errors
 
diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr
index abe24b662a2..3a15cc63f32 100644
--- a/tests/ui/traits/const-traits/trait-where-clause.stderr
+++ b/tests/ui/traits/const-traits/trait-where-clause.stderr
@@ -33,7 +33,7 @@ note: required by a bound in `Foo::b`
    |
 LL |     fn b() where Self: ~const Bar;
    |                        ^^^^^^^^^^ required by this bound in `Foo::b`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Bar`
    |
 LL | fn test1<T: Foo + Bar>() {
    |                 +++++
@@ -49,7 +49,7 @@ note: required by a bound in `Foo::c`
    |
 LL |     fn c<T: ~const Bar>();
    |             ^^^^^^^^^^ required by this bound in `Foo::c`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Bar`
    |
 LL | fn test1<T: Foo + Bar>() {
    |                 +++++
diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr
index 3bdb8b70172..45c26ac9ef4 100644
--- a/tests/ui/traits/copy-impl-cannot-normalize.stderr
+++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr
@@ -14,7 +14,7 @@ LL |     T: TraitFoo,
    |        -------- unsatisfied trait bound introduced here
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `TraitFoo`
    |
 LL | impl<T: TraitFoo> Copy for Foo<T> {}
    |       ++++++++++
diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr
index 56544dd4def..02170a127db 100644
--- a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr
+++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr
@@ -12,7 +12,7 @@ note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static`
    |
 LL | struct Bar<'lt>(Foo<'lt>);
    |                 ^^^^^^^^
-help: consider restricting type parameter `'any`
+help: consider restricting type parameter `'any` with  `'static`
    |
 LL | impl<'any: 'static> Copy for Bar<'any> {}
    |          +++++++++
diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr
index 6092c194a87..1816e029f18 100644
--- a/tests/ui/traits/inductive-overflow/two-traits.stderr
+++ b/tests/ui/traits/inductive-overflow/two-traits.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Magic::X`
    |
 LL |     type X: Trait;
    |             ^^^^^ required by this bound in `Magic::X`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Sync`
    |
 LL | impl<T: Magic + std::marker::Sync> Magic for T {
    |               +++++++++++++++++++
diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
index 6f7c9fa11d4..fdf0b1722be 100644
--- a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
+++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
@@ -18,7 +18,7 @@ LL |     c.same_as(22)
    |       |
    |       required by a bound introduced by this call
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `C` with trait `CompareTo`
    |
 LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
@@ -41,7 +41,7 @@ LL |     CompareTo::same_as(c, 22)
    |     |
    |     required by a bound introduced by this call
    |
-help: consider further restricting this bound
+help: consider further restricting type parameter `C` with trait `CompareTo`
    |
 LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
diff --git a/tests/ui/traits/issue-21837.stderr b/tests/ui/traits/issue-21837.stderr
index f1989392688..06e79d40c7d 100644
--- a/tests/ui/traits/issue-21837.stderr
+++ b/tests/ui/traits/issue-21837.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Foo`
    |
 LL | pub struct Foo<T: Bound>(T);
    |                   ^^^^^ required by this bound in `Foo`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Bound`
    |
 LL | impl<T: Bound> Trait2 for Foo<T> {}
    |       +++++++
diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr
index 2bf365745a6..1a6da70d76d 100644
--- a/tests/ui/traits/issue-43784-supertrait.stderr
+++ b/tests/ui/traits/issue-43784-supertrait.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `Complete`
    |
 LL | pub trait Complete: Partial {
    |                     ^^^^^^^ required by this bound in `Complete`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Complete for T {}
    |       +++++++++++++++++++
diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr
index cd8d8b3ffcd..463e50a2553 100644
--- a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr
+++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
 LL |     let x: <T as Trait>::Assoc = ();
    |            ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | fn test_poly<T: Trait>() {
    |               +++++++
diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr
index a720797efc4..6398fbddca5 100644
--- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr
+++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `copy`
    |
 LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
    |            ^^^^^ required by this bound in `copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
    |                  +++++++++++++++++++
@@ -38,7 +38,7 @@ LL |     copy::<dyn Setup<From=T>>(t)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `dyn Setup<From = T>`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
    |                  +++++++++++++++++++
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
index 1f319cc6743..da269bbeae4 100644
--- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
@@ -14,7 +14,7 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
 note: required by a bound in `Eq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL | pub struct Struct<T: std::clone::Clone>(T);
    |                    +++++++++++++++++++
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
index 09162970d33..d2a58e95629 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -32,7 +32,7 @@ error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not sati
 LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
    |                                               ^ the trait `Overlap<for<'a> fn(Assoc<'a, T>)>` is not implemented for `T`
    |
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Overlap`
    |
 LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {}
    |                                                                          ++++++++++++++++++++++++++++++++++++++
diff --git a/tests/ui/traits/next-solver/typeck/resolve-expectations.rs b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs
new file mode 100644
index 00000000000..d6b3816b9eb
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+fn id<T>(t: T) -> T { t }
+
+trait Foo {}
+impl Foo for i32 {}
+impl Foo for u32 {}
+
+fn main() {
+    // Make sure we resolve expected pointee of addr-of.
+    id::<<&&dyn Foo as Mirror>::Assoc>(&id(&1));
+
+    // Make sure we resolve expected element of array.
+    id::<<[Box<dyn Foo>; 2] as Mirror>::Assoc>([Box::new(1i32), Box::new(1u32)]);
+
+    // Make sure we resolve expected element of tuple.
+    id::<<(Box<dyn Foo>,) as Mirror>::Assoc>((Box::new(1i32),));
+}
diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs
new file mode 100644
index 00000000000..d406f3949a2
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs
@@ -0,0 +1,8 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+pub fn repro() -> impl FnMut() {
+    if true { || () } else { || () }
+}
+
+fn main() {}
diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr
index e3e29a73fdc..ccbc5ae2b75 100644
--- a/tests/ui/tuple/builtin-fail.stderr
+++ b/tests/ui/tuple/builtin-fail.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `assert_is_tuple`
    |
 LL | fn assert_is_tuple<T: std::marker::Tuple + ?Sized>() {}
    |                       ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with unstable trait `Tuple`
    |
 LL | fn from_param_env<T: std::marker::Tuple>() {
    |                    ++++++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
index 8f887a6ac68..bbb32b2d604 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
@@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL |     fn f<T: Clone>(t: T) -> X<T> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Clone`
    |
 LL |     pub type X<T: std::clone::Clone> = impl Clone;
    |                 +++++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr
index bca88b5fae1..c0f6d678097 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Struct`
    |
 LL | struct Struct<V: Display>(Option<V>);
    |                  ^^^^^^^ required by this bound in `Struct`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Display`
    |
 LL | type Foo<T: Debug + std::fmt::Display> = (impl Debug, Struct<T>);
    |                   +++++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr
index b20073fcdfc..047ad164239 100644
--- a/tests/ui/type-alias-impl-trait/future.stderr
+++ b/tests/ui/type-alias-impl-trait/future.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `foo`
    |
 LL | fn foo<B: Bar>(bar: B) -> FooFuture<B> {
    |           ^^^ required by this bound in `foo`
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Bar`
    |
 LL | type FooFuture<B: Bar> = impl Future<Output = ()>;
    |                 +++++
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index af6e6e1e66e..cd6e85764bd 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Debug`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index a847bed93da..bf3c4a0e04f 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Debug`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
    |              +++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
index 88529b370f1..98f99cdbfbd 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
@@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained`
    |
 LL | type Underconstrained<T: Trait> = impl Send;
    |                          ^^^^^ required by this bound
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> {
    |                    +++++++
@@ -30,7 +30,7 @@ note: required by a bound on the type alias `Underconstrained`
    |
 LL | type Underconstrained<T: Trait> = impl Send;
    |                          ^^^^^ required by this bound
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> {
    |                    +++++++
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index b3b9cbca968..5506977a3e7 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained`
    |
 LL | type Underconstrained<T: std::fmt::Debug> = impl Send;
    |                          ^^^^^^^^^^^^^^^ required by this bound
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Debug`
    |
 LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      +++++++++++++++++
@@ -25,7 +25,7 @@ note: required by a bound on the type alias `Underconstrained2`
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl Send;
    |                           ^^^^^^^^^^^^^^^ required by this bound
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `Debug`
    |
 LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> {
    |                          +++++++++++++++++
@@ -46,7 +46,7 @@ note: required by a bound on the type alias `Underconstrained`
    |
 LL | type Underconstrained<T: std::fmt::Debug> = impl Send;
    |                          ^^^^^^^^^^^^^^^ required by this bound
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Debug`
    |
 LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      +++++++++++++++++
@@ -67,7 +67,7 @@ note: required by a bound on the type alias `Underconstrained2`
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl Send;
    |                           ^^^^^^^^^^^^^^^ required by this bound
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `Debug`
    |
 LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> {
    |                          +++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr
index a6bdddbc98c..6673b03525d 100644
--- a/tests/ui/type-alias-impl-trait/issue-52843.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr
@@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL | fn foo<T: Default>(t: T) -> Foo<T> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Default`
    |
 LL | type Foo<T: std::default::Default> = impl Default;
    |           +++++++++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr
index f04750866c7..579902aa3ab 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `make_bug`
    |
 LL |     fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |                       ^^^^^^^ required by this bound in `make_bug`
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `From`
    |
 LL |     pub type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
    |                      +++++++++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr
index 91d71339a08..6fa7e197c40 100644
--- a/tests/ui/type-alias-impl-trait/issue-89686.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
 LL |         async move { self.f().await }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | type G<'a, T: Trait> = impl Future<Output = ()>;
    |             +++++++
diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr
index bc233a53214..afdccd56a50 100644
--- a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `<MyFoo as Foo>::foo`
    |
 LL |     fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
    |               ^^^ required by this bound in `<MyFoo as Foo>::foo`
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Bar`
    |
 LL |     type FooFn<B: Bar> = impl FnOnce();
    |                 +++++
diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
index 4a6a62bdf96..d4faa6e9392 100644
--- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
@@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL |     fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Bar`
    |
 LL |     type FooFn<B: Bar> = impl Baz;
    |                 +++++
diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr
index a2944a1acb9..e2fa9442323 100644
--- a/tests/ui/type-alias-impl-trait/not_well_formed.stderr
+++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr
@@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V`
 LL | type Foo<V> = impl Trait<V::Assoc>;
    |                             ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc`
    |
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `TraitWithAssoc`
    |
 LL | type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>;
    |           ++++++++++++++++
@@ -16,7 +16,7 @@ LL | type Foo<V> = impl Trait<V::Assoc>;
    |                             ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc`
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `TraitWithAssoc`
    |
 LL | type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>;
    |           ++++++++++++++++
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
index 48cef847fbb..e50949ed8f3 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL | fn _defining_use<T: Trait>() -> Converter<T> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | type Converter<T: Trait> = impl ProofForConversion<T>;
    |                 +++++++
diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
index 47bea7bbe60..9046a8a76b8 100644
--- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `mop`
    |
 LL |     fn mop<B: Bar>(bar: B) { bar.bar() }
    |               ^^^ required by this bound in `mop`
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Bar`
    |
 LL | type FooFn<B: Bar> = impl FnOnce(B);
    |             +++++
diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
index 09a42f73490..4156f0ca96a 100644
--- a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
+++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `foo`
    |
 LL | fn foo<B: Bar>(bar: B) -> FooFn<B> {
    |           ^^^ required by this bound in `foo`
-help: consider restricting type parameter `B`
+help: consider restricting type parameter `B` with trait `Bar`
    |
 LL | type FooFn<B: Bar> = impl FnOnce();
    |             +++++
diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr
index 96179a7b484..885c6ec9d8e 100644
--- a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr
+++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr
@@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `T`
 LL | type AssocOf<T> = T::Assoc;
    |                      ^^^^^ there is an associated type `Assoc` in the trait `Trait`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | type AssocOf<T: Trait> = T::Assoc;
    |               +++++++
@@ -15,7 +15,7 @@ error[E0220]: associated type `Assok` not found for `T`
 LL | type AssokOf<T> = T::Assok;
    |                      ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Trait`
    |
 LL | type AssokOf<T: Trait> = T::Assok;
    |               +++++++
@@ -30,7 +30,7 @@ error[E0220]: associated type `Proj` not found for `T`
 LL | type ProjOf<T> = T::Proj;
    |                     ^^^^ there is an associated type `Proj` in the trait `Parametrized`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Parametrized`
    |
 LL | type ProjOf<T: Parametrized</* 'a, T, N */>> = T::Proj;
    |              ++++++++++++++++++++++++++++++
diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr
index 9c482506129..ab3378eaa4a 100644
--- a/tests/ui/type/type-check-defaults.stderr
+++ b/tests/ui/type/type-check-defaults.stderr
@@ -53,7 +53,7 @@ note: required by a bound in `Super`
    |
 LL | trait Super<T: Copy> { }
    |                ^^^^ required by this bound in `Super`
-help: consider further restricting type parameter `T`
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL | trait Base<T = String>: Super<T> where T: std::marker::Copy { }
    |                                  ++++++++++++++++++++++++++
diff --git a/tests/ui/type/type-check/missing_trait_impl.stderr b/tests/ui/type/type-check/missing_trait_impl.stderr
index 2b58cd4180b..033b42e6736 100644
--- a/tests/ui/type/type-check/missing_trait_impl.stderr
+++ b/tests/ui/type/type-check/missing_trait_impl.stderr
@@ -6,7 +6,7 @@ LL |     let z = x + y;
    |             |
    |             T
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Add`
    |
 LL | fn foo<T: std::ops::Add>(x: T, y: T) {
    |         +++++++++++++++
@@ -19,7 +19,7 @@ LL |     x += x;
    |     |
    |     cannot use `+=` on type `T`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `AddAssign`
    |
 LL | fn bar<T: std::ops::AddAssign>(x: T) {
    |         +++++++++++++++++++++
@@ -30,7 +30,7 @@ error[E0600]: cannot apply unary operator `-` to type `T`
 LL |     let y = -x;
    |             ^^ cannot apply unary operator `-`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Neg`
    |
 LL | fn baz<T: std::ops::Neg>(x: T) {
    |         +++++++++++++++
@@ -41,7 +41,7 @@ error[E0600]: cannot apply unary operator `!` to type `T`
 LL |     let y = !x;
    |             ^^ cannot apply unary operator `!`
    |
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Not`
    |
 LL | fn baz<T: std::ops::Not>(x: T) {
    |         +++++++++++++++
diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr
index bd7fd0392c3..dd2ce092368 100644
--- a/tests/ui/typeck/bad-index-due-to-nested.stderr
+++ b/tests/ui/typeck/bad-index-due-to-nested.stderr
@@ -12,7 +12,7 @@ LL | impl<K, V> Index<&K> for HashMap<K, V>
 LL | where
 LL |     K: Hash,
    |        ---- unsatisfied trait bound introduced here
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Hash`
    |
 LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
    |               +++++++++++++++++
@@ -31,7 +31,7 @@ LL | impl<K, V> Index<&K> for HashMap<K, V>
 ...
 LL |     V: Copy,
    |        ---- unsatisfied trait bound introduced here
-help: consider restricting type parameter `V`
+help: consider restricting type parameter `V` with trait `Copy`
    |
 LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V {
    |                  +++++++++++++++++++
diff --git a/tests/ui/typeck/issue-90164.stderr b/tests/ui/typeck/issue-90164.stderr
index 43e96e1adc6..1be9c1a0b6e 100644
--- a/tests/ui/typeck/issue-90164.stderr
+++ b/tests/ui/typeck/issue-90164.stderr
@@ -13,7 +13,7 @@ note: required by a bound in `copy`
    |
 LL | fn copy<R: Unpin, W>(_: R, _: W) {}
    |            ^^^^^ required by this bound in `copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Unpin`
    |
 LL | fn f<T: std::marker::Unpin>(r: T) {
    |       ++++++++++++++++++++
diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr
index 537ae6b2b5f..d72c56ac712 100644
--- a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr
+++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_send`
    |
 LL | fn is_send<T:Send>() {
    |              ^^^^ required by this bound in `is_send`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Send`
    |
 LL | fn foo<T: std::marker::Send>() {
    |         +++++++++++++++++++
diff --git a/tests/ui/union/issue-81199.stderr b/tests/ui/union/issue-81199.stderr
index 0dd894beb2a..8b78ddcf4a5 100644
--- a/tests/ui/union/issue-81199.stderr
+++ b/tests/ui/union/issue-81199.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `PtrComponents`
    |
 LL | struct PtrComponents<T: Pointee + ?Sized> {
    |                         ^^^^^^^ required by this bound in `PtrComponents`
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Pointee`
    |
 LL | union PtrRepr<T: ?Sized + Pointee> {
    |                         +++++++++
diff --git a/tests/ui/unop/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr
index 0ae918d434a..5b81feaa578 100644
--- a/tests/ui/unop/unop-move-semantics.stderr
+++ b/tests/ui/unop/unop-move-semantics.stderr
@@ -15,7 +15,7 @@ help: consider cloning the value if the performance cost is acceptable
    |
 LL |     !x.clone();
    |       ++++++++
-help: consider further restricting this bound
+help: consider further restricting type parameter `T` with trait `Copy`
    |
 LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {
    |                                              ++++++
diff --git a/tests/ui/unsafe-fields/auto-traits.current.stderr b/tests/ui/unsafe-fields/auto-traits.current.stderr
new file mode 100644
index 00000000000..53a97458b7c
--- /dev/null
+++ b/tests/ui/unsafe-fields/auto-traits.current.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
+  --> $DIR/auto-traits.rs:24:22
+   |
+LL |     impl_unsafe_auto(UnsafeEnum::Safe(42));
+   |     ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `impl_unsafe_auto`
+  --> $DIR/auto-traits.rs:20:29
+   |
+LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {}
+   |                             ^^^^^^^^^^ required by this bound in `impl_unsafe_auto`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsafe-fields/auto-traits.next.stderr b/tests/ui/unsafe-fields/auto-traits.next.stderr
new file mode 100644
index 00000000000..53a97458b7c
--- /dev/null
+++ b/tests/ui/unsafe-fields/auto-traits.next.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
+  --> $DIR/auto-traits.rs:24:22
+   |
+LL |     impl_unsafe_auto(UnsafeEnum::Safe(42));
+   |     ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `impl_unsafe_auto`
+  --> $DIR/auto-traits.rs:20:29
+   |
+LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {}
+   |                             ^^^^^^^^^^ required by this bound in `impl_unsafe_auto`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsafe-fields/auto-traits.rs b/tests/ui/unsafe-fields/auto-traits.rs
new file mode 100644
index 00000000000..e15d0000079
--- /dev/null
+++ b/tests/ui/unsafe-fields/auto-traits.rs
@@ -0,0 +1,26 @@
+//@ compile-flags: --crate-type=lib
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(auto_traits)]
+#![feature(unsafe_fields)]
+#![allow(incomplete_features)]
+
+enum UnsafeEnum {
+    Safe(u8),
+    Unsafe { unsafe field: u8 },
+}
+
+auto trait SafeAuto {}
+
+fn impl_safe_auto(_: impl SafeAuto) {}
+
+unsafe auto trait UnsafeAuto {}
+
+fn impl_unsafe_auto(_: impl UnsafeAuto) {}
+
+fn tests() {
+    impl_safe_auto(UnsafeEnum::Safe(42));
+    impl_unsafe_auto(UnsafeEnum::Safe(42));
+    //~^ ERROR the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
+}
diff --git a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs b/tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs
index 95b928402a9..95b928402a9 100644
--- a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs
+++ b/tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs
diff --git a/tests/ui/unsafe-fields-crate.rs b/tests/ui/unsafe-fields/unsafe-fields-crate.rs
index cfb9ad6b544..cfb9ad6b544 100644
--- a/tests/ui/unsafe-fields-crate.rs
+++ b/tests/ui/unsafe-fields/unsafe-fields-crate.rs
diff --git a/tests/ui/unsafe-fields-crate.stderr b/tests/ui/unsafe-fields/unsafe-fields-crate.stderr
index 778c26e0a43..778c26e0a43 100644
--- a/tests/ui/unsafe-fields-crate.stderr
+++ b/tests/ui/unsafe-fields/unsafe-fields-crate.stderr
diff --git a/tests/ui/unsafe-fields-parse.rs b/tests/ui/unsafe-fields/unsafe-fields-parse.rs
index 67277731293..67277731293 100644
--- a/tests/ui/unsafe-fields-parse.rs
+++ b/tests/ui/unsafe-fields/unsafe-fields-parse.rs
diff --git a/tests/ui/unsafe-fields-parse.stderr b/tests/ui/unsafe-fields/unsafe-fields-parse.stderr
index 5a45ab03ffe..5a45ab03ffe 100644
--- a/tests/ui/unsafe-fields-parse.stderr
+++ b/tests/ui/unsafe-fields/unsafe-fields-parse.stderr
diff --git a/tests/ui/unsafe-fields.rs b/tests/ui/unsafe-fields/unsafe-fields.rs
index 637471582d7..637471582d7 100644
--- a/tests/ui/unsafe-fields.rs
+++ b/tests/ui/unsafe-fields/unsafe-fields.rs
diff --git a/tests/ui/unsafe-fields.stderr b/tests/ui/unsafe-fields/unsafe-fields.stderr
index a1c5d2b44cd..a1c5d2b44cd 100644
--- a/tests/ui/unsafe-fields.stderr
+++ b/tests/ui/unsafe-fields/unsafe-fields.stderr
diff --git a/tests/ui/unsized/issue-115809.rs b/tests/ui/unsized/issue-115809.rs
index 1b1d5234c12..d06b26061f8 100644
--- a/tests/ui/unsized/issue-115809.rs
+++ b/tests/ui/unsized/issue-115809.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --emit=link -Zmir-opt-level=2 -Zpolymorphize=on
+//@ compile-flags: --emit=link -Zmir-opt-level=2 -Zvalidate-mir
 
 fn foo<T>() {
     let a: [i32; 0] = [];
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs
index a953f1818c5..997bee1e600 100644
--- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs
@@ -3,15 +3,11 @@ trait Foo<const N: Bar<2>> {
     //~^ WARN trait objects without an explicit `dyn` are deprecated
     //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
     //~| ERROR cycle detected when computing type of `Foo::N`
-    //~| ERROR the trait `Foo` cannot be made into an object
-    //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
     fn func() {}
 }
 
 trait Bar<const M: Foo<2>> {}
 //~^ WARN trait objects without an explicit `dyn` are deprecated
 //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-//~| ERROR the trait `Foo` cannot be made into an object
-//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr
index f8905437c6e..733b729faf0 100644
--- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr
@@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> {
    |                    +++
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:20
    |
 LL | trait Bar<const M: Foo<2>> {}
    |                    ^^^^^^
@@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> {
    |           ^^^^^^^^^^^^^^^
    |
 note: ...which requires computing type of `Bar::M`...
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:11
    |
 LL | trait Bar<const M: Foo<2>> {}
    |           ^^^^^^^^^^^^^^^
@@ -44,69 +44,6 @@ LL | trait Foo<const N: Bar<2>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24
-   |
-LL | trait Foo<const N: Bar<2>> {
-   |                        ^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
-   |
-LL | trait Foo<const N: Bar<2>> {
-   |       --- this trait cannot be made into an object...
-...
-LL |     fn func() {}
-   |        ^^^^ ...because associated function `func` has no `self` parameter
-help: consider turning `func` into a method by giving it a `&self` argument
-   |
-LL |     fn func(&self) {}
-   |             +++++
-help: alternatively, consider constraining `func` so it does not apply to trait objects
-   |
-LL |     fn func() where Self: Sized {}
-   |               +++++++++++++++++
-
-error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20
-   |
-LL | trait Foo<const N: Bar<2>> {
-   |                    ^^^^^^
-   |
-   = note: the only supported types are integers, `bool`, and `char`
-
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
-   |
-LL | trait Bar<const M: Foo<2>> {}
-   |           ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
-   |
-LL | trait Foo<const N: Bar<2>> {
-   |       --- this trait cannot be made into an object...
-...
-LL |     fn func() {}
-   |        ^^^^ ...because associated function `func` has no `self` parameter
-help: consider turning `func` into a method by giving it a `&self` argument
-   |
-LL |     fn func(&self) {}
-   |             +++++
-help: alternatively, consider constraining `func` so it does not apply to trait objects
-   |
-LL |     fn func() where Self: Sized {}
-   |               +++++++++++++++++
-
-error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
-   |
-LL | trait Bar<const M: Foo<2>> {}
-   |                    ^^^^^^
-   |
-   = note: the only supported types are integers, `bool`, and `char`
-
-error: aborting due to 5 previous errors; 2 warnings emitted
+error: aborting due to 1 previous error; 2 warnings emitted
 
-Some errors have detailed explanations: E0038, E0391.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr
index 622d72f791e..3f87d3e0786 100644
--- a/tests/ui/wf/issue-96810.stderr
+++ b/tests/ui/wf/issue-96810.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `S`
    |
 LL | struct S<T: Tr>(T::Assoc);
    |             ^^ required by this bound in `S`
-help: consider restricting type parameter `K`
+help: consider restricting type parameter `K` with trait `Tr`
    |
 LL | struct Hoge<K: Tr> {
    |              ++++
diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr
index 78b5c6ec20e..1f37dc409fc 100644
--- a/tests/ui/wf/wf-enum-bound.stderr
+++ b/tests/ui/wf/wf-enum-bound.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL |     where T: ExtraCopy<U>, U: std::marker::Copy
    |                          ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr
index 2f2c1c2d266..f15a31887a2 100644
--- a/tests/ui/wf/wf-enum-fields-struct-variant.stderr
+++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `IsCopy`
    |
 LL | struct IsCopy<T:Copy> {
    |                 ^^^^ required by this bound in `IsCopy`
-help: consider restricting type parameter `A`
+help: consider restricting type parameter `A` with trait `Copy`
    |
 LL | enum AnotherEnum<A: std::marker::Copy> {
    |                   +++++++++++++++++++
diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr
index a5feaadfc75..3b4de77efdc 100644
--- a/tests/ui/wf/wf-enum-fields.stderr
+++ b/tests/ui/wf/wf-enum-fields.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `IsCopy`
    |
 LL | struct IsCopy<T:Copy> {
    |                 ^^^^ required by this bound in `IsCopy`
-help: consider restricting type parameter `A`
+help: consider restricting type parameter `A` with trait `Copy`
    |
 LL | enum SomeEnum<A: std::marker::Copy> {
    |                +++++++++++++++++++
diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr
index fbfe42ac624..76671dedabf 100644
--- a/tests/ui/wf/wf-fn-where-clause.stderr
+++ b/tests/ui/wf/wf-fn-where-clause.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy
    |                                    ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr
index 09e255bead0..47962c75d69 100644
--- a/tests/ui/wf/wf-impl-associated-type-trait.stderr
+++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MySet`
    |
 LL | pub struct MySet<T:MyHash> {
    |                    ^^^^^^ required by this bound in `MySet`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `MyHash`
    |
 LL | impl<T: MyHash> Foo for T {
    |       ++++++++
diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr
index 8f22edd17a1..a65f621526b 100644
--- a/tests/ui/wf/wf-in-fn-arg.stderr
+++ b/tests/ui/wf/wf-in-fn-arg.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ^^^^ required by this bound in `MustBeCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn bar<T: std::marker::Copy>(_: &MustBeCopy<T>)
    |         +++++++++++++++++++
diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr
index 1ae49a348cc..3f2b46f8478 100644
--- a/tests/ui/wf/wf-in-fn-ret.stderr
+++ b/tests/ui/wf/wf-in-fn-ret.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | struct MustBeCopy<T: Copy> {
    |                      ^^^^ required by this bound in `MustBeCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | fn bar<T: std::marker::Copy>() -> MustBeCopy<T>
    |         +++++++++++++++++++
diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr
index 17594c813da..4626b90500a 100644
--- a/tests/ui/wf/wf-in-fn-type-arg.stderr
+++ b/tests/ui/wf/wf-in-fn-type-arg.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ^^^^ required by this bound in `MustBeCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | struct Bar<T: std::marker::Copy> {
    |             +++++++++++++++++++
diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr
index fac535a1126..2ad405b4451 100644
--- a/tests/ui/wf/wf-in-fn-type-ret.stderr
+++ b/tests/ui/wf/wf-in-fn-type-ret.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ^^^^ required by this bound in `MustBeCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | struct Foo<T: std::marker::Copy> {
    |             +++++++++++++++++++
diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr
index 4c556d3d77d..6a56d1c032f 100644
--- a/tests/ui/wf/wf-in-fn-where-clause.stderr
+++ b/tests/ui/wf/wf-in-fn-where-clause.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | trait MustBeCopy<T:Copy> {
    |                    ^^^^ required by this bound in `MustBeCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL |     where T: MustBeCopy<U>, U: std::marker::Copy
    |                           ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr
index b96f56a12a5..5cd5bf5e24e 100644
--- a/tests/ui/wf/wf-in-obj-type-trait.stderr
+++ b/tests/ui/wf/wf-in-obj-type-trait.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy`
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ^^^^ required by this bound in `MustBeCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | struct Bar<T: std::marker::Copy> {
    |             +++++++++++++++++++
diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr
index 4cfbec12b6e..8b41bb17d2f 100644
--- a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr
+++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider restricting type parameter `U`
+help: consider restricting type parameter `U` with trait `Copy`
    |
 LL | impl<T,U: std::marker::Copy> Foo<T,U> {
    |         +++++++++++++++++++
diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr
index bdc1ee3e0e2..216b7a98b13 100644
--- a/tests/ui/wf/wf-inherent-impl-where-clause.stderr
+++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U>, U: std::marker::Copy
    |                                         ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr
index 4ac7f4634e4..24b4282538d 100644
--- a/tests/ui/wf/wf-struct-bound.stderr
+++ b/tests/ui/wf/wf-struct-bound.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL |     where T: ExtraCopy<U>, U: std::marker::Copy
    |                          ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr
index 241ced3c2db..4449b71bd88 100644
--- a/tests/ui/wf/wf-struct-field.stderr
+++ b/tests/ui/wf/wf-struct-field.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `IsCopy`
    |
 LL | struct IsCopy<T:Copy> {
    |                 ^^^^ required by this bound in `IsCopy`
-help: consider restricting type parameter `A`
+help: consider restricting type parameter `A` with trait `Copy`
    |
 LL | struct SomeStruct<A: std::marker::Copy> {
    |                    +++++++++++++++++++
diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr
index 4ea895a9b03..fe6a848f866 100644
--- a/tests/ui/wf/wf-trait-associated-type-bound.stderr
+++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | trait SomeTrait<T: std::marker::Copy> {
    |                  +++++++++++++++++++
diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr
index 5845d05b38e..0a8d9aa7be8 100644
--- a/tests/ui/wf/wf-trait-bound.stderr
+++ b/tests/ui/wf/wf-trait-bound.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider further restricting type parameter `U`
+help: consider further restricting type parameter `U` with trait `Copy`
    |
 LL |     where T: ExtraCopy<U>, U: std::marker::Copy
    |                          ++++++++++++++++++++++
diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr
index 3c05065e57f..9b0205bfe39 100644
--- a/tests/ui/wf/wf-trait-superbound.stderr
+++ b/tests/ui/wf/wf-trait-superbound.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy`
    |
 LL | trait ExtraCopy<T:Copy> { }
    |                   ^^^^ required by this bound in `ExtraCopy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | trait SomeTrait<T: std::marker::Copy>: ExtraCopy<T> {
    |                  +++++++++++++++++++
diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
index 2612cefef28..955ec18f465 100644
--- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
+++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `require_copy`
    |
 LL | fn require_copy<T: Copy>(x: T) {}
    |                    ^^^^ required by this bound in `require_copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Foo<T> {
    |       +++++++++++++++++++
diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
index 090df26a39e..793851a2871 100644
--- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
+++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `require_copy`
    |
 LL | fn require_copy<T: Copy>(x: T) {}
    |                    ^^^^ required by this bound in `require_copy`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` with trait `Copy`
    |
 LL | impl<T: std::marker::Copy> Foo<T> for Bar<T> {
    |       +++++++++++++++++++
diff --git a/x.py b/x.py
index 6c4c106817e..928a7496cb7 100755
--- a/x.py
+++ b/x.py
@@ -6,7 +6,7 @@
 
 # Parts of `bootstrap.py` use the `multiprocessing` module, so this entry point
 # must use the normal `if __name__ == '__main__':` convention to avoid problems.
-if __name__ == '__main__':
+if __name__ == "__main__":
     import os
     import sys
     import warnings
@@ -32,14 +32,16 @@ if __name__ == '__main__':
     # soft deprecation of old python versions
     skip_check = os.environ.get("RUST_IGNORE_OLD_PYTHON") == "1"
     if not skip_check and (major < 3 or (major == 3 and minor < 6)):
-        msg = cleandoc("""
+        msg = cleandoc(
+            """
             Using python {}.{} but >= 3.6 is recommended. Your python version
             should continue to work for the near future, but this will
             eventually change. If python >= 3.6 is not available on your system,
             please file an issue to help us understand timelines.
 
             This message can be suppressed by setting `RUST_IGNORE_OLD_PYTHON=1`
-        """.format(major, minor))
+        """.format(major, minor)
+        )
         warnings.warn(msg, stacklevel=1)
 
     rust_dir = os.path.dirname(os.path.abspath(__file__))
@@ -47,4 +49,5 @@ if __name__ == '__main__':
     sys.path.insert(0, os.path.join(rust_dir, "src", "bootstrap"))
 
     import bootstrap
+
     bootstrap.main()