about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock40
-rw-r--r--compiler/rustc_abi/src/layout.rs5
-rw-r--r--compiler/rustc_abi/src/lib.rs5
-rw-r--r--compiler/rustc_ast/src/ast.rs5
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs16
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs72
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs2
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl8
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs47
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs6
-rw-r--r--compiler/rustc_data_structures/Cargo.toml3
-rw-r--r--compiler/rustc_data_structures/src/marker.rs13
-rw-r--r--compiler/rustc_data_structures/src/sync.rs10
-rw-r--r--compiler/rustc_data_structures/src/sync/parallel.rs13
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs12
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0795.md4
-rw-r--r--compiler/rustc_errors/src/emitter.rs6
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs77
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs345
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs12
-rw-r--r--compiler/rustc_incremental/messages.ftl2
-rw-r--r--compiler/rustc_incremental/src/errors.rs6
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs20
-rw-r--r--compiler/rustc_interface/src/tests.rs12
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h1
-rw-r--r--compiler/rustc_macros/src/serialize.rs30
-rw-r--r--compiler/rustc_metadata/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs31
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/query/erase.rs22
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs3
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs26
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs26
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs14
-rw-r--r--compiler/rustc_mir_build/messages.ftl8
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs88
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs88
-rw-r--r--compiler/rustc_mir_build/src/errors.rs55
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs839
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs69
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs105
-rw-r--r--compiler/rustc_mir_transform/src/cross_crate_inline.rs10
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs28
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs3
-rw-r--r--compiler/rustc_parse/src/parser/item.rs12
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_session/src/code_stats.rs2
-rw-r--r--compiler/rustc_session/src/config.rs24
-rw-r--r--compiler/rustc_session/src/options.rs24
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs21
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs29
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs68
-rw-r--r--compiler/rustc_type_ir/src/flags.rs3
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs139
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs73
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs176
-rw-r--r--config.example.toml19
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/raw_vec.rs18
-rw-r--r--library/core/src/convert/mod.rs4
-rw-r--r--library/core/src/error.rs8
-rw-r--r--library/core/src/intrinsics.rs4
-rw-r--r--library/core/src/macros/mod.rs3
-rw-r--r--library/core/src/mem/maybe_uninit.rs17
-rw-r--r--library/core/src/mem/mod.rs4
-rw-r--r--library/core/src/ops/deref.rs162
-rw-r--r--library/core/src/primitive_docs.rs37
-rw-r--r--library/core/src/ptr/mod.rs10
-rw-r--r--library/core/src/slice/sort.rs13
-rw-r--r--library/core/src/task/wake.rs15
-rw-r--r--library/core/tests/mem.rs21
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/src/io/copy.rs76
-rw-r--r--library/std/src/io/readbuf.rs5
-rw-r--r--library/unwind/Cargo.toml3
-rw-r--r--library/unwind/build.rs25
-rw-r--r--library/unwind/src/lib.rs6
-rw-r--r--src/bootstrap/Cargo.lock40
-rw-r--r--src/bootstrap/defaults/config.codegen.toml2
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs37
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs113
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs16
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs120
-rw-r--r--src/bootstrap/src/core/builder.rs5
-rw-r--r--src/bootstrap/src/core/config/config.rs106
-rw-r--r--src/bootstrap/src/lib.rs9
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh8
-rw-r--r--src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock16
-rwxr-xr-xsrc/ci/docker/run.sh1
-rwxr-xr-xsrc/ci/run.sh4
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/aix.md26
-rw-r--r--src/etc/test-float-parse/Cargo.lock75
-rw-r--r--src/etc/test-float-parse/Cargo.toml2
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/clean/types.rs1
-rw-r--r--src/librustdoc/clean/utils.rs8
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/render/write_shared.rs15
-rw-r--r--src/librustdoc/html/templates/page.html1
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs150
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs2
-rw-r--r--src/tools/build-manifest/src/main.rs23
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs9
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.stdout4
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs2
-rw-r--r--src/tools/compiletest/src/common.rs14
-rw-r--r--src/tools/compiletest/src/header.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs22
-rw-r--r--src/tools/miri/README.md5
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs18
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs230
-rw-r--r--src/tools/miri/src/diagnostics.rs21
-rw-r--r--src/tools/miri/src/eval.rs8
-rw-r--r--src/tools/miri/src/shims/intrinsics/atomic.rs24
-rw-r--r--src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.rs2
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr12
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_load.stderr21
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.rs (renamed from src/tools/miri/tests/fail/concurrency/read_only_atomic_load.rs)2
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.stderr19
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.rs18
-rw-r--r--src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.stderr19
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_match_never.rs1
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.rs (renamed from src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs)0
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.stderr (renamed from src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr)8
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.rs12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.stderr25
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.rs (renamed from src/tools/miri/tests/pass/dangling_pointer_deref_match_underscore.rs)7
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.stderr25
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_read_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_read_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_write_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/fence_after_load.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/fence_after_load.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_read.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_read.stderr5
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_write.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_write.stderr5
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race1.stderr5
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race2.stderr5
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/relax_acquire_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/rmw_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/rmw_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race.stderr4
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr4
-rw-r--r--src/tools/miri/tests/fail/validity/match_binder_checks_validity1.rs (renamed from src/tools/miri/tests/pass/union-uninhabited-match-underscore.rs)4
-rw-r--r--src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr15
-rw-r--r--src/tools/miri/tests/fail/validity/match_binder_checks_validity2.rs14
-rw-r--r--src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr15
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs2
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr5
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs2
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr5
-rw-r--r--src/tools/miri/tests/pass/atomic-readonly-load.rs12
-rw-r--r--src/tools/miri/tests/pass/underscore_pattern.rs71
-rw-r--r--src/tools/miri/tests/pass/union-uninhabited-match-underscore.stdout1
-rw-r--r--src/tools/rust-installer/Cargo.toml1
-rw-r--r--src/tools/rustfmt/src/closures.rs2
-rw-r--r--src/tools/rustfmt/src/expr.rs2
-rw-r--r--src/tools/tidy/src/deps.rs231
-rw-r--r--src/tools/tidy/src/extdeps.rs36
-rw-r--r--tests/codegen/cross-crate-inlining/always-inline.rs13
-rw-r--r--tests/codegen/cross-crate-inlining/auxiliary/always.rs20
-rw-r--r--tests/codegen/cross-crate-inlining/auxiliary/leaf.rs20
-rw-r--r--tests/codegen/cross-crate-inlining/auxiliary/never.rs20
-rw-r--r--tests/codegen/cross-crate-inlining/leaf-inlining.rs20
-rw-r--r--tests/codegen/cross-crate-inlining/never-inline.rs13
-rw-r--r--tests/codegen/vec-reserve-extend.rs14
-rw-r--r--tests/coverage-map/README.md13
-rw-r--r--tests/coverage-map/if.cov-map15
-rw-r--r--tests/coverage-map/if.rs9
-rw-r--r--tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs (renamed from tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs)0
-rw-r--r--tests/coverage-run-rustdoc/doctest.coverage (renamed from tests/run-coverage-rustdoc/doctest.coverage)0
-rw-r--r--tests/coverage-run-rustdoc/doctest.rs (renamed from tests/run-coverage-rustdoc/doctest.rs)0
-rw-r--r--tests/coverage/README.md16
-rw-r--r--tests/coverage/abort.cov-map (renamed from tests/coverage-map/status-quo/abort.cov-map)0
-rw-r--r--tests/coverage/abort.coverage (renamed from tests/run-coverage/abort.coverage)0
-rw-r--r--tests/coverage/abort.rs (renamed from tests/coverage-map/status-quo/abort.rs)0
-rw-r--r--tests/coverage/assert.cov-map (renamed from tests/coverage-map/status-quo/assert.cov-map)0
-rw-r--r--tests/coverage/assert.coverage (renamed from tests/run-coverage/assert.coverage)0
-rw-r--r--tests/coverage/assert.rs (renamed from tests/coverage-map/status-quo/assert.rs)0
-rw-r--r--tests/coverage/async.cov-map (renamed from tests/coverage-map/status-quo/async.cov-map)0
-rw-r--r--tests/coverage/async.coverage (renamed from tests/run-coverage/async.coverage)0
-rw-r--r--tests/coverage/async.rs (renamed from tests/coverage-map/status-quo/async.rs)0
-rw-r--r--tests/coverage/async2.cov-map (renamed from tests/coverage-map/status-quo/async2.cov-map)0
-rw-r--r--tests/coverage/async2.coverage (renamed from tests/run-coverage/async2.coverage)0
-rw-r--r--tests/coverage/async2.rs (renamed from tests/coverage-map/status-quo/async2.rs)0
-rw-r--r--tests/coverage/auxiliary/inline_always_with_dead_code.rs (renamed from tests/run-coverage/auxiliary/inline_always_with_dead_code.rs)0
-rw-r--r--tests/coverage/auxiliary/unused_mod_helper.rs (renamed from tests/run-coverage/auxiliary/unused_mod_helper.rs)0
-rw-r--r--tests/coverage/auxiliary/used_crate.rs (renamed from tests/run-coverage/auxiliary/used_crate.rs)0
-rw-r--r--tests/coverage/auxiliary/used_inline_crate.rs (renamed from tests/run-coverage/auxiliary/used_inline_crate.rs)0
-rw-r--r--tests/coverage/bad_counter_ids.cov-map (renamed from tests/coverage-map/status-quo/bad_counter_ids.cov-map)0
-rw-r--r--tests/coverage/bad_counter_ids.coverage (renamed from tests/run-coverage/bad_counter_ids.coverage)0
-rw-r--r--tests/coverage/bad_counter_ids.rs (renamed from tests/coverage-map/status-quo/bad_counter_ids.rs)0
-rw-r--r--tests/coverage/closure.cov-map (renamed from tests/coverage-map/status-quo/closure.cov-map)0
-rw-r--r--tests/coverage/closure.coverage (renamed from tests/run-coverage/closure.coverage)0
-rw-r--r--tests/coverage/closure.rs (renamed from tests/coverage-map/status-quo/closure.rs)0
-rw-r--r--tests/coverage/closure_bug.cov-map (renamed from tests/coverage-map/status-quo/closure_bug.cov-map)0
-rw-r--r--tests/coverage/closure_bug.coverage (renamed from tests/run-coverage/closure_bug.coverage)0
-rw-r--r--tests/coverage/closure_bug.rs (renamed from tests/coverage-map/status-quo/closure_bug.rs)0
-rw-r--r--tests/coverage/closure_macro.cov-map (renamed from tests/coverage-map/status-quo/closure_macro.cov-map)0
-rw-r--r--tests/coverage/closure_macro.coverage (renamed from tests/run-coverage/closure_macro.coverage)0
-rw-r--r--tests/coverage/closure_macro.rs (renamed from tests/coverage-map/status-quo/closure_macro.rs)0
-rw-r--r--tests/coverage/closure_macro_async.cov-map (renamed from tests/coverage-map/status-quo/closure_macro_async.cov-map)0
-rw-r--r--tests/coverage/closure_macro_async.coverage (renamed from tests/run-coverage/closure_macro_async.coverage)0
-rw-r--r--tests/coverage/closure_macro_async.rs (renamed from tests/coverage-map/status-quo/closure_macro_async.rs)0
-rw-r--r--tests/coverage/conditions.cov-map (renamed from tests/coverage-map/status-quo/conditions.cov-map)0
-rw-r--r--tests/coverage/conditions.coverage (renamed from tests/run-coverage/conditions.coverage)0
-rw-r--r--tests/coverage/conditions.rs (renamed from tests/coverage-map/status-quo/conditions.rs)0
-rw-r--r--tests/coverage/continue.cov-map (renamed from tests/coverage-map/status-quo/continue.cov-map)0
-rw-r--r--tests/coverage/continue.coverage (renamed from tests/run-coverage/continue.coverage)0
-rw-r--r--tests/coverage/continue.rs (renamed from tests/coverage-map/status-quo/continue.rs)0
-rw-r--r--tests/coverage/coroutine.cov-map (renamed from tests/coverage-map/status-quo/coroutine.cov-map)0
-rw-r--r--tests/coverage/coroutine.coverage (renamed from tests/run-coverage/coroutine.coverage)0
-rw-r--r--tests/coverage/coroutine.rs (renamed from tests/coverage-map/status-quo/coroutine.rs)0
-rw-r--r--tests/coverage/dead_code.cov-map (renamed from tests/coverage-map/status-quo/dead_code.cov-map)0
-rw-r--r--tests/coverage/dead_code.coverage (renamed from tests/run-coverage/dead_code.coverage)0
-rw-r--r--tests/coverage/dead_code.rs (renamed from tests/coverage-map/status-quo/dead_code.rs)0
-rw-r--r--tests/coverage/drop_trait.cov-map (renamed from tests/coverage-map/status-quo/drop_trait.cov-map)0
-rw-r--r--tests/coverage/drop_trait.coverage (renamed from tests/run-coverage/drop_trait.coverage)0
-rw-r--r--tests/coverage/drop_trait.rs (renamed from tests/coverage-map/status-quo/drop_trait.rs)0
-rw-r--r--tests/coverage/fn_sig_into_try.cov-map (renamed from tests/coverage-map/fn_sig_into_try.cov-map)0
-rw-r--r--tests/coverage/fn_sig_into_try.coverage (renamed from tests/run-coverage/fn_sig_into_try.coverage)0
-rw-r--r--tests/coverage/fn_sig_into_try.rs (renamed from tests/coverage-map/fn_sig_into_try.rs)0
-rw-r--r--tests/coverage/generics.cov-map (renamed from tests/coverage-map/status-quo/generics.cov-map)0
-rw-r--r--tests/coverage/generics.coverage (renamed from tests/run-coverage/generics.coverage)0
-rw-r--r--tests/coverage/generics.rs (renamed from tests/coverage-map/status-quo/generics.rs)0
-rw-r--r--tests/coverage/if.cov-map (renamed from tests/coverage-map/status-quo/if.cov-map)0
-rw-r--r--tests/coverage/if.coverage (renamed from tests/run-coverage/if.coverage)0
-rw-r--r--tests/coverage/if.rs (renamed from tests/coverage-map/status-quo/if.rs)0
-rw-r--r--tests/coverage/if_else.cov-map (renamed from tests/coverage-map/status-quo/if_else.cov-map)0
-rw-r--r--tests/coverage/if_else.coverage (renamed from tests/run-coverage/if_else.coverage)0
-rw-r--r--tests/coverage/if_else.rs (renamed from tests/coverage-map/status-quo/if_else.rs)0
-rw-r--r--tests/coverage/inline-dead.cov-map (renamed from tests/coverage-map/status-quo/inline-dead.cov-map)0
-rw-r--r--tests/coverage/inline-dead.coverage (renamed from tests/run-coverage/inline-dead.coverage)0
-rw-r--r--tests/coverage/inline-dead.rs (renamed from tests/coverage-map/status-quo/inline-dead.rs)0
-rw-r--r--tests/coverage/inline.cov-map (renamed from tests/coverage-map/status-quo/inline.cov-map)0
-rw-r--r--tests/coverage/inline.coverage (renamed from tests/run-coverage/inline.coverage)0
-rw-r--r--tests/coverage/inline.rs (renamed from tests/coverage-map/status-quo/inline.rs)0
-rw-r--r--tests/coverage/inner_items.cov-map (renamed from tests/coverage-map/status-quo/inner_items.cov-map)0
-rw-r--r--tests/coverage/inner_items.coverage (renamed from tests/run-coverage/inner_items.coverage)0
-rw-r--r--tests/coverage/inner_items.rs (renamed from tests/coverage-map/status-quo/inner_items.rs)0
-rw-r--r--tests/coverage/issue-83601.cov-map (renamed from tests/coverage-map/status-quo/issue-83601.cov-map)0
-rw-r--r--tests/coverage/issue-83601.coverage (renamed from tests/run-coverage/issue-83601.coverage)0
-rw-r--r--tests/coverage/issue-83601.rs (renamed from tests/coverage-map/status-quo/issue-83601.rs)0
-rw-r--r--tests/coverage/issue-84561.cov-map (renamed from tests/coverage-map/status-quo/issue-84561.cov-map)0
-rw-r--r--tests/coverage/issue-84561.coverage (renamed from tests/run-coverage/issue-84561.coverage)0
-rw-r--r--tests/coverage/issue-84561.rs (renamed from tests/coverage-map/status-quo/issue-84561.rs)0
-rw-r--r--tests/coverage/issue-85461.cov-map8
-rw-r--r--tests/coverage/issue-85461.coverage (renamed from tests/run-coverage/issue-85461.coverage)0
-rw-r--r--tests/coverage/issue-85461.rs (renamed from tests/run-coverage/issue-85461.rs)0
-rw-r--r--tests/coverage/issue-93054.cov-map (renamed from tests/coverage-map/status-quo/issue-93054.cov-map)0
-rw-r--r--tests/coverage/issue-93054.coverage (renamed from tests/run-coverage/issue-93054.coverage)0
-rw-r--r--tests/coverage/issue-93054.rs (renamed from tests/coverage-map/status-quo/issue-93054.rs)0
-rw-r--r--tests/coverage/lazy_boolean.cov-map (renamed from tests/coverage-map/status-quo/lazy_boolean.cov-map)0
-rw-r--r--tests/coverage/lazy_boolean.coverage (renamed from tests/run-coverage/lazy_boolean.coverage)0
-rw-r--r--tests/coverage/lazy_boolean.rs (renamed from tests/coverage-map/status-quo/lazy_boolean.rs)0
-rw-r--r--tests/coverage/long_and_wide.cov-map (renamed from tests/coverage-map/long_and_wide.cov-map)0
-rw-r--r--tests/coverage/long_and_wide.coverage151
-rw-r--r--tests/coverage/long_and_wide.rs (renamed from tests/coverage-map/long_and_wide.rs)0
-rw-r--r--tests/coverage/loop_break_value.cov-map (renamed from tests/coverage-map/status-quo/loop_break_value.cov-map)0
-rw-r--r--tests/coverage/loop_break_value.coverage (renamed from tests/run-coverage/loop_break_value.coverage)0
-rw-r--r--tests/coverage/loop_break_value.rs (renamed from tests/coverage-map/status-quo/loop_break_value.rs)0
-rw-r--r--tests/coverage/loops_branches.cov-map (renamed from tests/coverage-map/status-quo/loops_branches.cov-map)0
-rw-r--r--tests/coverage/loops_branches.coverage (renamed from tests/run-coverage/loops_branches.coverage)0
-rw-r--r--tests/coverage/loops_branches.rs (renamed from tests/coverage-map/status-quo/loops_branches.rs)0
-rw-r--r--tests/coverage/match_or_pattern.cov-map (renamed from tests/coverage-map/status-quo/match_or_pattern.cov-map)0
-rw-r--r--tests/coverage/match_or_pattern.coverage (renamed from tests/run-coverage/match_or_pattern.coverage)0
-rw-r--r--tests/coverage/match_or_pattern.rs (renamed from tests/coverage-map/status-quo/match_or_pattern.rs)0
-rw-r--r--tests/coverage/nested_loops.cov-map (renamed from tests/coverage-map/status-quo/nested_loops.cov-map)0
-rw-r--r--tests/coverage/nested_loops.coverage (renamed from tests/run-coverage/nested_loops.coverage)0
-rw-r--r--tests/coverage/nested_loops.rs (renamed from tests/coverage-map/status-quo/nested_loops.rs)0
-rw-r--r--tests/coverage/no_cov_crate.cov-map (renamed from tests/coverage-map/status-quo/no_cov_crate.cov-map)0
-rw-r--r--tests/coverage/no_cov_crate.coverage (renamed from tests/run-coverage/no_cov_crate.coverage)0
-rw-r--r--tests/coverage/no_cov_crate.rs (renamed from tests/coverage-map/status-quo/no_cov_crate.rs)0
-rw-r--r--tests/coverage/overflow.cov-map (renamed from tests/coverage-map/status-quo/overflow.cov-map)8
-rw-r--r--tests/coverage/overflow.coverage (renamed from tests/run-coverage/overflow.coverage)1
-rw-r--r--tests/coverage/overflow.rs (renamed from tests/coverage-map/status-quo/overflow.rs)1
-rw-r--r--tests/coverage/panic_unwind.cov-map (renamed from tests/coverage-map/status-quo/panic_unwind.cov-map)0
-rw-r--r--tests/coverage/panic_unwind.coverage (renamed from tests/run-coverage/panic_unwind.coverage)0
-rw-r--r--tests/coverage/panic_unwind.rs (renamed from tests/coverage-map/status-quo/panic_unwind.rs)0
-rw-r--r--tests/coverage/partial_eq.cov-map (renamed from tests/coverage-map/status-quo/partial_eq.cov-map)0
-rw-r--r--tests/coverage/partial_eq.coverage (renamed from tests/run-coverage/partial_eq.coverage)0
-rw-r--r--tests/coverage/partial_eq.rs (renamed from tests/coverage-map/status-quo/partial_eq.rs)0
-rw-r--r--tests/coverage/simple_loop.cov-map (renamed from tests/coverage-map/status-quo/simple_loop.cov-map)0
-rw-r--r--tests/coverage/simple_loop.coverage (renamed from tests/run-coverage/simple_loop.coverage)0
-rw-r--r--tests/coverage/simple_loop.rs (renamed from tests/coverage-map/status-quo/simple_loop.rs)0
-rw-r--r--tests/coverage/simple_match.cov-map (renamed from tests/coverage-map/status-quo/simple_match.cov-map)0
-rw-r--r--tests/coverage/simple_match.coverage (renamed from tests/run-coverage/simple_match.coverage)0
-rw-r--r--tests/coverage/simple_match.rs (renamed from tests/coverage-map/status-quo/simple_match.rs)0
-rw-r--r--tests/coverage/sort_groups.cov-map (renamed from tests/coverage-map/status-quo/sort_groups.cov-map)29
-rw-r--r--tests/coverage/sort_groups.coverage (renamed from tests/run-coverage/sort_groups.coverage)2
-rw-r--r--tests/coverage/sort_groups.rs (renamed from tests/coverage-map/status-quo/sort_groups.rs)2
-rw-r--r--tests/coverage/test_harness.cov-map (renamed from tests/coverage-map/status-quo/test_harness.cov-map)0
-rw-r--r--tests/coverage/test_harness.coverage (renamed from tests/run-coverage/test_harness.coverage)0
-rw-r--r--tests/coverage/test_harness.rs (renamed from tests/coverage-map/status-quo/test_harness.rs)0
-rw-r--r--tests/coverage/tight_inf_loop.cov-map (renamed from tests/coverage-map/status-quo/tight_inf_loop.cov-map)0
-rw-r--r--tests/coverage/tight_inf_loop.coverage (renamed from tests/run-coverage/tight_inf_loop.coverage)0
-rw-r--r--tests/coverage/tight_inf_loop.rs (renamed from tests/coverage-map/status-quo/tight_inf_loop.rs)0
-rw-r--r--tests/coverage/trivial.cov-map (renamed from tests/coverage-map/trivial.cov-map)0
-rw-r--r--tests/coverage/trivial.coverage4
-rw-r--r--tests/coverage/trivial.rs (renamed from tests/coverage-map/trivial.rs)0
-rw-r--r--tests/coverage/try_error_result.cov-map (renamed from tests/coverage-map/status-quo/try_error_result.cov-map)0
-rw-r--r--tests/coverage/try_error_result.coverage (renamed from tests/run-coverage/try_error_result.coverage)0
-rw-r--r--tests/coverage/try_error_result.rs (renamed from tests/coverage-map/status-quo/try_error_result.rs)0
-rw-r--r--tests/coverage/unreachable.cov-map (renamed from tests/coverage-map/unreachable.cov-map)0
-rw-r--r--tests/coverage/unreachable.coverage (renamed from tests/run-coverage/unreachable.coverage)0
-rw-r--r--tests/coverage/unreachable.rs (renamed from tests/coverage-map/unreachable.rs)0
-rw-r--r--tests/coverage/unused.cov-map (renamed from tests/coverage-map/status-quo/unused.cov-map)0
-rw-r--r--tests/coverage/unused.coverage (renamed from tests/run-coverage/unused.coverage)0
-rw-r--r--tests/coverage/unused.rs (renamed from tests/coverage-map/status-quo/unused.rs)0
-rw-r--r--tests/coverage/unused_mod.cov-map16
-rw-r--r--tests/coverage/unused_mod.coverage (renamed from tests/run-coverage/unused_mod.coverage)0
-rw-r--r--tests/coverage/unused_mod.rs (renamed from tests/run-coverage/unused_mod.rs)0
-rw-r--r--tests/coverage/uses_crate.cov-map40
-rw-r--r--tests/coverage/uses_crate.coverage (renamed from tests/run-coverage/uses_crate.coverage)0
-rw-r--r--tests/coverage/uses_crate.rs (renamed from tests/run-coverage/uses_crate.rs)0
-rw-r--r--tests/coverage/uses_inline_crate.cov-map55
-rw-r--r--tests/coverage/uses_inline_crate.coverage (renamed from tests/run-coverage/uses_inline_crate.coverage)0
-rw-r--r--tests/coverage/uses_inline_crate.rs (renamed from tests/run-coverage/uses_inline_crate.rs)0
-rw-r--r--tests/coverage/while.cov-map (renamed from tests/coverage-map/status-quo/while.cov-map)0
-rw-r--r--tests/coverage/while.coverage (renamed from tests/run-coverage/while.coverage)0
-rw-r--r--tests/coverage/while.rs (renamed from tests/coverage-map/status-quo/while.rs)0
-rw-r--r--tests/coverage/while_early_ret.cov-map (renamed from tests/coverage-map/status-quo/while_early_ret.cov-map)0
-rw-r--r--tests/coverage/while_early_ret.coverage (renamed from tests/run-coverage/while_early_ret.coverage)0
-rw-r--r--tests/coverage/while_early_ret.rs (renamed from tests/coverage-map/status-quo/while_early_ret.rs)0
-rw-r--r--tests/coverage/yield.cov-map (renamed from tests/coverage-map/status-quo/yield.cov-map)0
-rw-r--r--tests/coverage/yield.coverage (renamed from tests/run-coverage/yield.coverage)0
-rw-r--r--tests/coverage/yield.rs (renamed from tests/coverage-map/status-quo/yield.rs)0
-rw-r--r--tests/debuginfo/simple-struct.rs2
-rw-r--r--tests/mir-opt/building/while_storage.rs60
-rw-r--r--tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir70
-rw-r--r--tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir70
-rw-r--r--tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff91
-rw-r--r--tests/mir-opt/const_debuginfo.rs17
-rw-r--r--tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff (renamed from tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff)0
-rw-r--r--tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff (renamed from tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff)0
-rw-r--r--tests/mir-opt/const_prop/indirect_mutation.rs41
-rw-r--r--tests/mir-opt/const_prop/offset_of.rs2
-rw-r--r--tests/mir-opt/const_prop_miscompile.rs24
-rw-r--r--tests/mir-opt/while_storage.rs21
-rw-r--r--tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir16
-rw-r--r--tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir16
-rw-r--r--tests/run-coverage/abort.rs66
-rw-r--r--tests/run-coverage/assert.rs32
-rw-r--r--tests/run-coverage/async.rs128
-rw-r--r--tests/run-coverage/async2.rs57
-rw-r--r--tests/run-coverage/bad_counter_ids.rs66
-rw-r--r--tests/run-coverage/closure.rs220
-rw-r--r--tests/run-coverage/closure_bug.rs44
-rw-r--r--tests/run-coverage/closure_macro.rs40
-rw-r--r--tests/run-coverage/closure_macro_async.rs77
-rw-r--r--tests/run-coverage/conditions.rs86
-rw-r--r--tests/run-coverage/continue.rs69
-rw-r--r--tests/run-coverage/coroutine.rs30
-rw-r--r--tests/run-coverage/dead_code.rs37
-rw-r--r--tests/run-coverage/drop_trait.rs33
-rw-r--r--tests/run-coverage/fn_sig_into_try.rs41
-rw-r--r--tests/run-coverage/generics.rs44
-rw-r--r--tests/run-coverage/if.rs28
-rw-r--r--tests/run-coverage/if_else.rs40
-rw-r--r--tests/run-coverage/inline-dead.rs27
-rw-r--r--tests/run-coverage/inline.rs51
-rw-r--r--tests/run-coverage/inner_items.rs57
-rw-r--r--tests/run-coverage/issue-83601.rs14
-rw-r--r--tests/run-coverage/issue-84561.rs182
-rw-r--r--tests/run-coverage/issue-93054.rs30
-rw-r--r--tests/run-coverage/lazy_boolean.rs61
-rw-r--r--tests/run-coverage/loop_break_value.rs13
-rw-r--r--tests/run-coverage/loops_branches.rs60
-rw-r--r--tests/run-coverage/match_or_pattern.rs43
-rw-r--r--tests/run-coverage/nested_loops.rs25
-rw-r--r--tests/run-coverage/no_cov_crate.rs88
-rw-r--r--tests/run-coverage/overflow.rs63
-rw-r--r--tests/run-coverage/panic_unwind.rs31
-rw-r--r--tests/run-coverage/partial_eq.rs46
-rw-r--r--tests/run-coverage/simple_loop.rs35
-rw-r--r--tests/run-coverage/simple_match.rs43
-rw-r--r--tests/run-coverage/sort_groups.rs23
-rw-r--r--tests/run-coverage/test_harness.rs10
-rw-r--r--tests/run-coverage/tight_inf_loop.rs5
-rw-r--r--tests/run-coverage/try_error_result.rs118
-rw-r--r--tests/run-coverage/unreachable.rs37
-rw-r--r--tests/run-coverage/unused.rs41
-rw-r--r--tests/run-coverage/while.rs5
-rw-r--r--tests/run-coverage/while_early_ret.rs42
-rw-r--r--tests/run-coverage/yield.rs37
-rw-r--r--tests/rustdoc/const-effect-param.rs2
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs16
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/const-fn.rs5
-rw-r--r--tests/rustdoc/inline_cross/const-effect-param.rs29
-rw-r--r--tests/rustdoc/inline_cross/const-fn.rs10
-rw-r--r--tests/rustdoc/issue-115295-macro-const-display.rs40
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--tests/ui/atomic-from-mut-not-available.stderr4
-rw-r--r--tests/ui/binop/false-binop-caused-by-missing-semi.fixed10
-rw-r--r--tests/ui/binop/false-binop-caused-by-missing-semi.rs10
-rw-r--r--tests/ui/binop/false-binop-caused-by-missing-semi.stderr17
-rw-r--r--tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr4
-rw-r--r--tests/ui/consts/assert-type-intrinsics.rs1
-rw-r--r--tests/ui/consts/assert-type-intrinsics.stderr12
-rw-r--r--tests/ui/consts/const-blocks/fn-call-in-non-const.stderr6
-rw-r--r--tests/ui/consts/const-blocks/trait-error.stderr6
-rw-r--r--tests/ui/consts/const-fn-in-vec.rs8
-rw-r--r--tests/ui/consts/const-fn-in-vec.stderr44
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-move-errors.rs96
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-move-errors.stderr174
-rw-r--r--tests/ui/derives/deriving-with-repr-packed.stderr1
-rw-r--r--tests/ui/error-codes/E0004.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-offset-of-enum.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-offset-of-enum.stderr37
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs2
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr24
-rw-r--r--tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs20
-rw-r--r--tests/ui/hygiene/panic-location.run.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/async-and-ret-ref.rs11
-rw-r--r--tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr14
-rw-r--r--tests/ui/late-bound-lifetimes/predicate-is-global.rs40
-rw-r--r--tests/ui/macros/stringify.rs31
-rw-r--r--tests/ui/match/match_non_exhaustive.stderr4
-rw-r--r--tests/ui/methods/disambiguate-multiple-blanket-impl.stderr12
-rw-r--r--tests/ui/methods/disambiguate-multiple-impl.stderr8
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait-2.stderr28
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait.stderr12
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.stderr8
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr4
-rw-r--r--tests/ui/mir/alignment/addrof_alignment.rs (renamed from tests/ui/mir/addrof_alignment.rs)3
-rw-r--r--tests/ui/mir/alignment/i686-pc-windows-msvc.rs (renamed from tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs)4
-rw-r--r--tests/ui/mir/alignment/misaligned_lhs.rs (renamed from tests/ui/mir/mir_alignment_check.rs)4
-rw-r--r--tests/ui/mir/alignment/misaligned_rhs.rs13
-rw-r--r--tests/ui/mir/alignment/packed.rs29
-rw-r--r--tests/ui/mir/alignment/place_computation.rs16
-rw-r--r--tests/ui/mir/alignment/place_without_read.rs9
-rw-r--r--tests/ui/mir/alignment/two_pointers.rs15
-rw-r--r--tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr6
-rw-r--r--tests/ui/offset-of/offset-of-enum.rs2
-rw-r--r--tests/ui/offset-of/offset-of-private.rs2
-rw-r--r--tests/ui/parser/emoji-identifiers.stderr6
-rw-r--r--tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed8
-rw-r--r--tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs8
-rw-r--r--tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr11
-rw-r--r--tests/ui/pattern/issue-94866.stderr4
-rw-r--r--tests/ui/pattern/usefulness/conflicting_bindings.rs24
-rw-r--r--tests/ui/pattern/usefulness/conflicting_bindings.stderr66
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr18
-rw-r--r--tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr94
-rw-r--r--tests/ui/pattern/usefulness/empty-match.normal.stderr94
-rw-r--r--tests/ui/pattern/usefulness/empty-match.rs18
-rw-r--r--tests/ui/pattern/usefulness/issue-35609.stderr3
-rw-r--r--tests/ui/pattern/usefulness/issue-39362.stderr6
-rw-r--r--tests/ui/pattern/usefulness/issue-40221.stderr6
-rw-r--r--tests/ui/pattern/usefulness/issue-56379.stderr10
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs18
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr54
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr4
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match.stderr8
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr33
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-patterns.stderr6
-rw-r--r--tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr6
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-patterns.stderr6
-rw-r--r--tests/ui/resolve/fn-new-doesnt-exist.rs5
-rw-r--r--tests/ui/resolve/fn-new-doesnt-exist.stderr14
-rw-r--r--tests/ui/resolve/issue-82865.stderr7
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr75
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr31
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs53
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs18
-rw-r--r--tests/ui/span/issue-37767.stderr8
-rw-r--r--tests/ui/suggestions/deref-path-method.stderr7
-rw-r--r--tests/ui/suggestions/issue-109291.stderr7
-rw-r--r--tests/ui/target-feature/similar-feature-suggestion.stderr4
-rw-r--r--tests/ui/target-feature/unstable-feature.rs6
-rw-r--r--tests/ui/target-feature/unstable-feature.stderr6
-rw-r--r--tests/ui/thread-local/thread-local-static.mir.stderr (renamed from tests/ui/thread-local/thread-local-static.stderr)10
-rw-r--r--tests/ui/thread-local/thread-local-static.rs3
-rw-r--r--tests/ui/thread-local/thread-local-static.thir.stderr44
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.rs2
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.stderr11
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.rs2
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.stderr11
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr11
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr11
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.rs16
-rw-r--r--tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs19
-rw-r--r--tests/ui/traits/object/print_vtable_sizes.stdout22
-rw-r--r--tests/ui/union/union-unsafe.mir.stderr28
-rw-r--r--tests/ui/union/union-unsafe.rs14
-rw-r--r--tests/ui/union/union-unsafe.thir.stderr30
-rw-r--r--tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr (renamed from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr)4
-rw-r--r--tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs10
-rw-r--r--tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr16
-rw-r--r--tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr10
-rw-r--r--tests/ui/unsafe/ranged_ints2.rs1
-rw-r--r--tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr10
-rw-r--r--tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr10
-rw-r--r--tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed (renamed from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed)19
-rw-r--r--tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr (renamed from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr)26
-rw-r--r--tests/ui/unsafe/wrapping-unsafe-block-sugg.rs19
-rw-r--r--tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed73
-rw-r--r--tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr99
-rw-r--r--triagebot.toml7
601 files changed, 5773 insertions, 5079 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d56d7e3f2b0..adaac69af57 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -722,9 +722,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.101"
+version = "0.1.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a6d58e9c3408138099a396a98fd0d0e6cfb25d723594d2ae48b5004513fd5b"
+checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1281,26 +1281,15 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
 
 [[package]]
 name = "errno"
-version = "0.3.1"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
 dependencies = [
- "errno-dragonfly",
  "libc",
  "windows-sys 0.48.0",
 ]
 
 [[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
 name = "error_index_generator"
 version = "0.0.0"
 dependencies = [
@@ -2055,7 +2044,6 @@ dependencies = [
  "anyhow",
  "clap",
  "flate2",
- "num_cpus",
  "rayon",
  "tar",
  "walkdir",
@@ -2215,9 +2203,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
 
 [[package]]
 name = "libc"
-version = "0.2.149"
+version = "0.2.150"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
+checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -3005,9 +2993,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "1.4.2"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e"
+checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b"
 
 [[package]]
 name = "ppv-lite86"
@@ -3181,9 +3169,9 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.7.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
 dependencies = [
  "either",
  "rayon-core",
@@ -3191,14 +3179,12 @@ dependencies = [
 
 [[package]]
 name = "rayon-core"
-version = "1.11.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
 dependencies = [
- "crossbeam-channel",
  "crossbeam-deque",
  "crossbeam-utils",
- "num_cpus",
 ]
 
 [[package]]
@@ -3734,6 +3720,7 @@ dependencies = [
  "measureme",
  "memmap2",
  "parking_lot 0.12.1",
+ "portable-atomic",
  "rustc-hash",
  "rustc-rayon",
  "rustc-rayon-core",
@@ -5923,7 +5910,6 @@ dependencies = [
 name = "unwind"
 version = "0.0.0"
 dependencies = [
- "cc",
  "cfg-if",
  "compiler_builtins",
  "core",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 9127e1d06e8..996fd5bbecf 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -906,9 +906,8 @@ fn univariant<
                 use rand::{seq::SliceRandom, SeedableRng};
                 // `ReprOptions.layout_seed` is a deterministic seed we can use to randomize field
                 // ordering.
-                let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(
-                    repr.field_shuffle_seed.as_u64(),
-                );
+                let mut rng =
+                    rand_xoshiro::Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
 
                 // Shuffle the ordering of the fields.
                 optimizing.shuffle(&mut rng);
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 8e7aa59ee34..09a87cf8e2f 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -76,15 +76,14 @@ pub struct ReprOptions {
     pub align: Option<Align>,
     pub pack: Option<Align>,
     pub flags: ReprFlags,
-    #[cfg(feature = "randomize")]
     /// The seed to be used for randomizing a type's layout
     ///
-    /// Note: This could technically be a `Hash128` which would
+    /// Note: This could technically be a `u128` which would
     /// be the "most accurate" hash as it'd encompass the item and crate
     /// hash without loss, but it does pay the price of being larger.
     /// Everything's a tradeoff, a 64-bit seed should be sufficient for our
     /// purposes (primarily `-Z randomize-layout`)
-    pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64,
+    pub field_shuffle_seed: u64,
 }
 
 impl ReprOptions {
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 146a4db200c..c85ff6f5c44 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1548,7 +1548,10 @@ pub struct QSelf {
 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum CaptureBy {
     /// `move |x| y + x`.
-    Value,
+    Value {
+        /// The span of the `move` keyword.
+        move_kw: Span,
+    },
     /// `move` keyword was not specified.
     Ref,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 0634ee970ec..7c0a78253a2 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -302,6 +302,10 @@ pub trait MutVisitor: Sized {
     fn visit_format_args(&mut self, fmt: &mut FormatArgs) {
         noop_visit_format_args(fmt, self)
     }
+
+    fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) {
+        noop_visit_capture_by(capture_by, self)
+    }
 }
 
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -1397,7 +1401,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
         }
         ExprKind::Closure(box Closure {
             binder,
-            capture_clause: _,
+            capture_clause,
             constness,
             asyncness,
             movability: _,
@@ -1409,6 +1413,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
             vis.visit_closure_binder(binder);
             visit_constness(constness, vis);
             vis.visit_asyncness(asyncness);
+            vis.visit_capture_by(capture_clause);
             vis.visit_fn_decl(fn_decl);
             vis.visit_expr(body);
             vis.visit_span(fn_decl_span);
@@ -1562,6 +1567,15 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
     vis.visit_span(&mut visibility.span);
 }
 
+pub fn noop_visit_capture_by<T: MutVisitor>(capture_by: &mut CaptureBy, vis: &mut T) {
+    match capture_by {
+        CaptureBy::Ref => {}
+        CaptureBy::Value { move_kw } => {
+            vis.visit_span(move_kw);
+        }
+    }
+}
+
 /// Some value for the AST node that is valid but possibly meaningless.
 pub trait DummyAstNode {
     fn dummy() -> Self;
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e091961a144..1caa39e2dd9 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -251,6 +251,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
         walk_inline_asm_sym(self, sym)
     }
+    fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) {
+        // Nothing to do
+    }
 }
 
 #[macro_export]
@@ -857,7 +860,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         }
         ExprKind::Closure(box Closure {
             binder,
-            capture_clause: _,
+            capture_clause,
             asyncness: _,
             constness: _,
             movability: _,
@@ -866,6 +869,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             fn_decl_span: _,
             fn_arg_span: _,
         }) => {
+            visitor.visit_capture_by(capture_clause);
             visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id)
         }
         ExprKind::Block(block, opt_label) => {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c73d2382db8..9a70e6d7c4a 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1201,7 +1201,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
 
             let async_expr = this.make_async_expr(
-                CaptureBy::Value,
+                CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
                 closure_id,
                 None,
                 body.span,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index e71f421659e..48421ff7140 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -146,37 +146,49 @@ pub fn print_crate<'a>(
     s.s.eof()
 }
 
-/// This makes printed token streams look slightly nicer,
-/// and also addresses some specific regressions described in #63896 and #73345.
-fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool {
-    if let TokenTree::Token(token, _) = prev {
-        // No space after these tokens, e.g. `x.y`, `$e`
-        // (The carets point to `prev`.)       ^     ^
-        if matches!(token.kind, token::Dot | token::Dollar) {
-            return false;
-        }
-        if let token::DocComment(comment_kind, ..) = token.kind {
-            return comment_kind != CommentKind::Line;
-        }
-    }
-    match curr {
-        // No space before these tokens, e.g. `foo,`, `println!`, `x.y`
-        // (The carets point to `curr`.)          ^           ^     ^
+/// Should two consecutive tokens be printed with a space between them?
+///
+/// Note: some old proc macros parse pretty-printed output, so changes here can
+/// break old code. For example:
+/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
+/// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)]
+///
+fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
+    use token::*;
+    use Delimiter::*;
+    use TokenTree::Delimited as Del;
+    use TokenTree::Token as Tok;
+
+    // Each match arm has one or more examples in comments. The default is to
+    // insert space between adjacent tokens, except for the cases listed in
+    // this match.
+    match (tt1, tt2) {
+        // No space after line doc comments.
+        (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,
+
+        // `.` + ANYTHING: `x.y`, `tup.0`
+        // `$` + ANYTHING: `$e`
+        (Tok(Token { kind: Dot | Dollar, .. }, _), _) => false,
+
+        // ANYTHING + `,`: `foo,`
+        // ANYTHING + `.`: `x.y`, `tup.0`
+        // ANYTHING + `!`: `foo! { ... }`
         //
-        // FIXME: having `Not` here works well for macro invocations like
-        // `println!()`, but is bad when `!` means "logical not" or "the never
-        // type", where the lack of space causes ugliness like this:
-        // `Fn() ->!`, `x =! y`, `if! x { f(); }`.
-        TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
-        // No space before parentheses if preceded by these tokens, e.g. `foo(...)`
-        TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
-        }
-        // No space before brackets if preceded by these tokens, e.g. `#[...]`
-        TokenTree::Delimited(_, Delimiter::Bracket, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
-        }
-        TokenTree::Delimited(..) => true,
+        // FIXME: Incorrect cases:
+        // - Logical not: `x =! y`, `if! x { f(); }`
+        // - Never type: `Fn() ->!`
+        (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false,
+
+        // IDENT + `(`: `f(3)`
+        //
+        // FIXME: Incorrect cases:
+        // - Let: `let(a, b) = (1, 2)`
+        (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false,
+
+        // `#` + `[`: `#[attr]`
+        (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false,
+
+        _ => true,
     }
 }
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index e84af12d3f9..edbc3500373 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -673,7 +673,7 @@ impl<'a> State<'a> {
 
     fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
         match capture_clause {
-            ast::CaptureBy::Value => self.word_space("move"),
+            ast::CaptureBy::Value { .. } => self.word_space("move"),
             ast::CaptureBy::Ref => {}
         }
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 695ac6980cd..41d6b98d7cf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -2,7 +2,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
 use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
 
 use crate::diagnostics::CapturedMessageOpt;
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
@@ -488,6 +488,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         args_span,
                     }
                 });
+
+                self.add_note_for_packed_struct_derive(err, original_path.local);
             }
         }
     }
@@ -594,4 +596,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             );
         }
     }
+
+    /// Adds an explanatory note if the move error occurs in a derive macro
+    /// expansion of a packed struct.
+    /// Such errors happen because derive macro expansions shy away from taking
+    /// references to the struct's fields since doing so would be undefined behaviour
+    fn add_note_for_packed_struct_derive(&self, err: &mut Diagnostic, local: Local) {
+        let local_place: PlaceRef<'tcx> = local.into();
+        let local_ty = local_place.ty(self.body.local_decls(), self.infcx.tcx).ty.peel_refs();
+
+        if let Some(adt) = local_ty.ty_adt_def()
+            && adt.repr().packed()
+            && let ExpnKind::Macro(MacroKind::Derive, name) = self.body.span.ctxt().outer_expn_data().kind
+        {
+            err.note(format!("`#[derive({name})]` triggers a move because taking references to the fields of a packed struct is undefined behaviour"));
+        }
+    }
 }
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 92da0c069e5..8c2fa6ee95f 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -108,7 +108,7 @@ pub fn expand_env<'cx>(
 
             return DummyResult::any(sp);
         }
-        Some(value) => cx.expr_str(sp, value),
+        Some(value) => cx.expr_str(span, value),
     };
     MacEager::expr(e)
 }
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index c0cfe39f1e0..7a86ddc7556 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -76,8 +76,8 @@ codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$
 codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
 
 codegen_llvm_unknown_ctarget_feature =
-    unknown feature specified for `-Ctarget-feature`: `{$feature}`
-    .note = it is still passed through to the codegen backend
+    unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
     .possible_feature = you might have meant: `{$rust_feature}`
     .consider_filing_feature_request = consider filing a feature request
 
@@ -87,6 +87,10 @@ codegen_llvm_unknown_ctarget_feature_prefix =
 
 codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo
 
+codegen_llvm_unstable_ctarget_feature =
+    unstable feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = this feature is not stably supported; its behavior can change in the future
+
 codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
 
 codegen_llvm_write_ir = failed to write LLVM IR to {$path}
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 73821b1685d..307c1264dc1 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -374,15 +374,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
 
             let g = self.get_static(def_id);
 
-            // boolean SSA values are i1, but they have to be stored in i8 slots,
-            // otherwise some LLVM optimization passes don't work as expected
-            let mut val_llty = self.val_ty(v);
-            let v = if val_llty == self.type_i1() {
-                val_llty = self.type_i8();
-                llvm::LLVMConstZExt(v, val_llty)
-            } else {
-                v
-            };
+            let val_llty = self.val_ty(v);
 
             let instance = Instance::mono(self.tcx, def_id);
             let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 665d195790c..10ca5ad802a 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -26,6 +26,13 @@ pub(crate) struct UnknownCTargetFeature<'a> {
     pub rust_feature: PossibleFeature<'a>,
 }
 
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_unstable_ctarget_feature)]
+#[note]
+pub(crate) struct UnstableCTargetFeature<'a> {
+    pub feature: &'a str,
+}
+
 #[derive(Subdiagnostic)]
 pub(crate) enum PossibleFeature<'a> {
     #[help(codegen_llvm_possible_feature)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index a038b3af03d..7fc02a95be0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -969,7 +969,6 @@ extern "C" {
         ConstantIndices: *const &'a Value,
         NumIndices: c_uint,
     ) -> &'a Value;
-    pub fn LLVMConstZExt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
     pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
     pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
     pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 7c8ef67ffd1..cc4ccaf19c2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -1,7 +1,7 @@
 use crate::back::write::create_informational_target_machine;
 use crate::errors::{
     PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
-    UnknownCTargetFeaturePrefix,
+    UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
 };
 use crate::llvm;
 use libc::c_int;
@@ -531,25 +531,34 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
             };
 
             let feature = backend_feature_name(s)?;
-            // Warn against use of LLVM specific feature names on the CLI.
-            if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) {
-                let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
-                    let llvm_features = to_llvm_features(sess, rust_feature);
-                    if llvm_features.contains(&feature) && !llvm_features.contains(&rust_feature) {
-                        Some(rust_feature)
+            // Warn against use of LLVM specific feature names and unstable features on the CLI.
+            if diagnostics {
+                let feature_state = supported_features.iter().find(|&&(v, _)| v == feature);
+                if feature_state.is_none() {
+                    let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
+                        let llvm_features = to_llvm_features(sess, rust_feature);
+                        if llvm_features.contains(&feature)
+                            && !llvm_features.contains(&rust_feature)
+                        {
+                            Some(rust_feature)
+                        } else {
+                            None
+                        }
+                    });
+                    let unknown_feature = if let Some(rust_feature) = rust_feature {
+                        UnknownCTargetFeature {
+                            feature,
+                            rust_feature: PossibleFeature::Some { rust_feature },
+                        }
                     } else {
-                        None
-                    }
-                });
-                let unknown_feature = if let Some(rust_feature) = rust_feature {
-                    UnknownCTargetFeature {
-                        feature,
-                        rust_feature: PossibleFeature::Some { rust_feature },
-                    }
-                } else {
-                    UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
-                };
-                sess.emit_warning(unknown_feature);
+                        UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+                    };
+                    sess.emit_warning(unknown_feature);
+                } else if feature_state.is_some_and(|(_name, feature_gate)| feature_gate.is_some())
+                {
+                    // An unstable feature. Warn about using it.
+                    sess.emit_warning(UnstableCTargetFeature { feature });
+                }
             }
 
             if diagnostics {
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 9c053338c85..2936f1de3cb 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -23,6 +23,15 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
 // check whether they're named already elsewhere in rust
 // e.g. in stdarch and whether the given name matches LLVM's
 // if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted
+//
+// When adding a new feature, be particularly mindful of features that affect function ABIs. Those
+// need to be treated very carefully to avoid introducing unsoundness! This often affects features
+// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an
+// example of this going wrong), but features enabling new SIMD registers are also a concern (see
+// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong).
+//
+// Stabilizing a target feature (setting the 2nd component of the pair to `None`) requires t-lang
+// approval.
 
 const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // tidy-alphabetical-start
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index ac8123bc1be..35744d9a167 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -104,11 +104,7 @@ pub trait CodegenBackend {
         outputs: &OutputFilenames,
     ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>;
 
-    /// This is called on the returned `Box<dyn Any>` from `join_codegen`
-    ///
-    /// # Panics
-    ///
-    /// Panics when the passed `Box<dyn Any>` was not returned by `join_codegen`.
+    /// This is called on the returned `CodegenResults` from `join_codegen`
     fn link(
         &self,
         sess: &Session,
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 2701fdbbd77..8d91c4c4376 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -47,6 +47,9 @@ features = [
 memmap2 = "0.2.1"
 # tidy-alphabetical-end
 
+[target.'cfg(any(target_arch = "powerpc", target_arch = "mips"))'.dependencies]
+portable-atomic = "1.5.1"
+
 [features]
 # tidy-alphabetical-start
 rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"]
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index a8c442377fb..266e54604a6 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -138,7 +138,6 @@ cfg_match! {
             [std::sync::atomic::AtomicUsize]
             [std::sync::atomic::AtomicU8]
             [std::sync::atomic::AtomicU32]
-            [std::sync::atomic::AtomicU64]
             [std::backtrace::Backtrace]
             [std::io::Error]
             [std::fs::File]
@@ -148,6 +147,18 @@ cfg_match! {
             [crate::owned_slice::OwnedSlice]
         );
 
+        // PowerPC and MIPS platforms with 32-bit pointers do not
+        // have AtomicU64 type.
+        #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
+        already_sync!(
+            [std::sync::atomic::AtomicU64]
+        );
+
+        #[cfg(any(target_arch = "powerpc", target_arch = "mips"))]
+        already_sync!(
+            [portable_atomic::AtomicU64]
+        );
+
         macro_rules! impl_dyn_sync {
             ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
                 $(unsafe impl<$($generics2)*> DynSync for $ty {})*
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index f957734b04d..43221d70e21 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -265,7 +265,15 @@ cfg_match! {
 
         pub use std::sync::OnceLock;
 
-        pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
+        pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32};
+
+        // PowerPC and MIPS platforms with 32-bit pointers do not
+        // have AtomicU64 type.
+        #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
+        pub use std::sync::atomic::AtomicU64;
+
+        #[cfg(any(target_arch = "powerpc", target_arch = "mips"))]
+        pub use portable_atomic::AtomicU64;
 
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index 39dddb59569..5695d839d3e 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -77,12 +77,12 @@ mod disabled {
         })
     }
 
-    pub fn try_par_for_each_in<T: IntoIterator, E: Copy>(
+    pub fn try_par_for_each_in<T: IntoIterator, E>(
         t: T,
         mut for_each: impl FnMut(T::Item) -> Result<(), E>,
     ) -> Result<(), E> {
         parallel_guard(|guard| {
-            t.into_iter().fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
+            t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and)
         })
     }
 
@@ -178,7 +178,7 @@ mod enabled {
 
     pub fn try_par_for_each_in<
         T: IntoIterator + IntoParallelIterator<Item = <T as IntoIterator>::Item>,
-        E: Copy + Send,
+        E: Send,
     >(
         t: T,
         for_each: impl Fn(<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend,
@@ -187,11 +187,10 @@ mod enabled {
             if mode::is_dyn_thread_safe() {
                 let for_each = FromDyn::from(for_each);
                 t.into_par_iter()
-                    .fold_with(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
-                    .reduce(|| Ok(()), |a, b| a.and(b))
+                    .filter_map(|i| guard.run(|| for_each(i)))
+                    .reduce(|| Ok(()), Result::and)
             } else {
-                t.into_iter()
-                    .fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
+                t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and)
             }
         })
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index ee4337754a9..84ae45d6a2b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -41,6 +41,7 @@ use rustc_session::cstore::MetadataLoader;
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
 use rustc_session::{config, EarlyErrorHandler, Session};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
@@ -421,8 +422,12 @@ fn run_compiler(
                     // effects of writing the dep-info and reporting errors.
                     queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(()));
                 } else {
-                    let krate = queries.parse()?.steal();
-                    pretty::print(sess, *ppm, pretty::PrintExtra::AfterParsing { krate });
+                    let krate = queries.parse()?;
+                    pretty::print(
+                        sess,
+                        *ppm,
+                        pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() },
+                    );
                 }
                 trace!("finished pretty-printing");
                 return early_exit();
@@ -477,8 +482,7 @@ fn run_compiler(
             }
 
             if sess.opts.unstable_opts.print_vtable_sizes {
-                let crate_name =
-                    compiler.session().opts.crate_name.as_deref().unwrap_or("<UNKNOWN_CRATE>");
+                let crate_name = queries.global_ctxt()?.enter(|tcx| tcx.crate_name(LOCAL_CRATE));
 
                 sess.code_stats.print_vtable_sizes(crate_name);
             }
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 8c6fee83013..cc533b9941a 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -217,7 +217,7 @@ fn write_or_print(out: &str, sess: &Session) {
 // Extra data for pretty-printing, the form of which depends on what kind of
 // pretty-printing we are doing.
 pub enum PrintExtra<'tcx> {
-    AfterParsing { krate: ast::Crate },
+    AfterParsing { krate: &'tcx ast::Crate },
     NeedsAstMap { tcx: TyCtxt<'tcx> },
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md
index 8b4b2dc87fd..20f51441c29 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0795.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0795.md
@@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro.
 Erroneous code example:
 
 ```compile_fail,E0795
-#![feature(offset_of)]
+#![feature(offset_of, offset_of_enum)]
 
 let x = std::mem::offset_of!(Option<u8>, Some);
 ```
@@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option<u8>` can be found by specifying
 the field name `0`:
 
 ```
-#![feature(offset_of)]
+#![feature(offset_of, offset_of_enum)]
 
 let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
 ```
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 6d95fbcfad0..68dba860291 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2362,11 +2362,7 @@ impl FileWithAnnotatedLines {
 
                 let label = label.as_ref().map(|m| {
                     normalize_whitespace(
-                        &emitter
-                            .translate_message(m, &args)
-                            .map_err(Report::new)
-                            .unwrap()
-                            .to_string(),
+                        &emitter.translate_message(m, &args).map_err(Report::new).unwrap(),
                     )
                 });
 
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 11782e33d84..64b5a7d2921 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -526,6 +526,8 @@ declare_features! (
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
     (unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None),
+    /// Allows using enums in offset_of!
+    (unstable, offset_of_enum, "CURRENT_RUSTC_VERSION", Some(106655), None),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882), None),
     /// Allows exhaustive integer pattern matching on `usize` and `isize`.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index d88f165b9e5..c4e44a6a4e3 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3566,6 +3566,15 @@ impl<'hir> OwnerNode<'hir> {
         }
     }
 
+    pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
+        match self {
+            OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
+            _ => None,
+        }
+    }
+
     pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
         match self {
             OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 90babbb63a0..857515f971a 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2162,7 +2162,7 @@ pub(super) fn check_type_bounds<'tcx>(
     impl_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
+    let param_env = tcx.param_env(impl_ty.def_id);
     debug!(?param_env);
 
     let container_id = impl_ty.container_id(tcx);
@@ -2217,8 +2217,14 @@ pub(super) fn check_type_bounds<'tcx>(
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
 
+    // Normalize predicates with the assumption that the GAT may always normalize
+    // to its definition type. This should be the param-env we use to *prove* the
+    // predicate too, but we don't do that because of performance issues.
+    // See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
+    let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
     for mut obligation in util::elaborate(tcx, obligations) {
-        let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate);
+        let normalized_predicate =
+            ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
         debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
         obligation.predicate = normalized_predicate;
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 046983e90f7..eb4491b89bf 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -32,6 +32,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
 };
+use rustc_type_ir::TypeFlags;
 
 use std::cell::LazyCell;
 use std::ops::{ControlFlow, Deref};
@@ -1877,7 +1878,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
                 continue;
             }
             // Match the existing behavior.
-            if pred.is_global() && !pred.has_late_bound_vars() {
+            if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) {
                 let pred = self.normalize(span, None, pred);
                 let hir_node = tcx.hir().find_by_def_id(self.body_def_id);
 
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index ebb9e6f42d9..6424d1c7931 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -880,7 +880,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                             (pair, r)
                         })
                         .unzip();
-                self.record_late_bound_vars(hir_id, binders.clone());
+                self.record_late_bound_vars(hir_id, binders);
                 // Even if there are no lifetimes defined here, we still wrap it in a binder
                 // scope. If there happens to be a nested poly trait ref (an error), that
                 // will be `Concatenating` anyways, so we don't have to worry about the depth
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 1ce6bb6ca15..5f82d9f06c6 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2017,7 +2017,7 @@ impl<'a> State<'a> {
 
     fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
         match capture_clause {
-            hir::CaptureBy::Value => self.word_space("move"),
+            hir::CaptureBy::Value { .. } => self.word_space("move"),
             hir::CaptureBy::Ref => {}
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index a11fe10c01c..9f439a2b32a 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -13,7 +13,7 @@ use crate::errors::{
     YieldExprOutsideOfCoroutine,
 };
 use crate::fatally_break_rust;
-use crate::method::{MethodCallComponents, SelfSource};
+use crate::method::SelfSource;
 use crate::type_error_struct;
 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
 use crate::{
@@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
+            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
         let ty = match res {
             Res::Err => {
                 self.suggest_assoc_method_call(segs);
@@ -959,12 +959,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Applicability::MachineApplicable,
             );
         });
+        self.check_for_missing_semi(lhs, &mut err);
 
         adjust_err(&mut err);
 
         err.emit();
     }
 
+    /// Check if the expression that could not be assigned to was a typoed expression that
+    pub fn check_for_missing_semi(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+    ) -> bool {
+        if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind
+            && let hir::BinOpKind::Mul = binop.node
+            && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span))
+            && rhs.is_syntactic_place_expr()
+        {
+            //      v missing semicolon here
+            // foo()
+            // *bar = baz;
+            // (#80446).
+            err.span_suggestion_verbose(
+                lhs.span.shrink_to_hi(),
+                "you might have meant to write a semicolon here",
+                ";".to_string(),
+                Applicability::MachineApplicable,
+            );
+            return true;
+        }
+        false
+    }
+
     // Check if an expression `original_expr_id` comes from the condition of a while loop,
     /// as opposed from the body of a while loop, which we can naively check by iterating
     /// parents until we find a loop...
@@ -1305,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         segment.ident,
                         SelfSource::MethodCall(rcvr),
                         error,
-                        Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }),
+                        Some(args),
                         expected,
                         false,
                     ) {
@@ -1524,21 +1551,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             _ => {}
         }
-        // If someone calls a const fn, they can extract that call out into a separate constant (or a const
-        // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
-        let is_const_fn = match element.kind {
+        // If someone calls a const fn or constructs a const value, they can extract that
+        // out into a separate constant (or a const block in the future), so we check that
+        // to tell them that in the diagnostic. Does not affect typeck.
+        let is_constable = match element.kind {
             hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
-                ty::FnDef(def_id, _) => tcx.is_const_fn(def_id),
-                _ => false,
+                ty::FnDef(def_id, _) if tcx.is_const_fn(def_id) => traits::IsConstable::Fn,
+                _ => traits::IsConstable::No,
             },
-            _ => false,
+            hir::ExprKind::Path(qpath) => {
+                match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
+                    Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
+                    _ => traits::IsConstable::No,
+                }
+            }
+            _ => traits::IsConstable::No,
         };
 
         // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
         // don't copy that one element, we move it. Only check for Copy if the length is larger.
         if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
             let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
-            let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
+            let code = traits::ObligationCauseCode::RepeatElementCopy {
+                is_constable,
+                elt_type: element_ty,
+                elt_span: element.span,
+                elt_stmt_span: self
+                    .tcx
+                    .hir()
+                    .parent_iter(element.hir_id)
+                    .find_map(|(_, node)| match node {
+                        hir::Node::Item(it) => Some(it.span),
+                        hir::Node::Stmt(stmt) => Some(stmt.span),
+                        _ => None,
+                    })
+                    .expect("array repeat expressions must be inside an item or statement"),
+            };
             self.require_type_meets(element_ty, element.span, code, lang_item);
         }
     }
@@ -3119,6 +3167,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let (ident, _def_scope) =
                         self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
 
+                    if !self.tcx.features().offset_of_enum {
+                        rustc_session::parse::feature_err(
+                            &self.tcx.sess.parse_sess,
+                            sym::offset_of_enum,
+                            ident.span,
+                            "using enums in offset_of is experimental",
+                        ).emit();
+                    }
+
                     let Some((index, variant)) = container_def.variants()
                         .iter_enumerated()
                         .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index b5a07f0d3e9..750ed2c3491 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &'tcx QPath<'tcx>,
         hir_id: hir::HirId,
         span: Span,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
         debug!(
             "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
@@ -898,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         item_name,
                         SelfSource::QPath(qself),
                         error,
-                        None,
+                        args,
                         Expectation::NoExpectation,
                         trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 86a0e95de1d..d69d2529b18 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,7 +7,7 @@ mod prelude2021;
 pub mod probe;
 mod suggest;
 
-pub use self::suggest::{MethodCallComponents, SelfSource};
+pub use self::suggest::SelfSource;
 pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 12cc5ed2f1a..b1a2df8ace4 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -34,7 +34,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
-use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
+use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
@@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
 use std::cmp::{self, Ordering};
 use std::iter;
 
-/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
-/// components readily available to us to point at the right place in diagnostics.
-#[derive(Debug, Clone, Copy)]
-pub struct MethodCallComponents<'tcx> {
-    pub receiver: &'tcx hir::Expr<'tcx>,
-    pub args: &'tcx [hir::Expr<'tcx>],
-    pub full_expr: &'tcx hir::Expr<'tcx>,
-}
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
         let tcx = self.tcx;
@@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.note_candidates_on_method_error(
                     rcvr_ty,
                     item_name,
+                    source,
                     args,
                     span,
                     &mut err,
@@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_missing_writer(
         &self,
         rcvr_ty: Ty<'tcx>,
-        args: MethodCallComponents<'tcx>,
+        rcvr_expr: &hir::Expr<'tcx>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
         let mut err = struct_span_err!(
             self.tcx.sess,
-            args.receiver.span,
+            rcvr_expr.span,
             E0599,
             "cannot write into `{}`",
             ty_str
         );
         err.span_note(
-            args.receiver.span,
+            rcvr_expr.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
         );
-        if let ExprKind::Lit(_) = args.receiver.kind {
+        if let ExprKind::Lit(_) = rcvr_expr.kind {
             err.span_help(
-                args.receiver.span.shrink_to_lo(),
+                rcvr_expr.span.shrink_to_lo(),
                 "a writer is needed before this format string",
             );
         };
@@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
@@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
         }) && item_name.name == Symbol::intern("write_fmt");
-        let mut err = if is_write && let Some(args) = args {
-            self.suggest_missing_writer(rcvr_ty, args)
-        } else {
-            tcx.sess.create_err(NoAssociatedItem {
-                span,
-                item_kind,
-                item_name,
-                ty_prefix: if trait_missing_method {
-                    // FIXME(mu001999) E0599 maybe not suitable here because it is for types
-                    Cow::from("trait")
-                } else {
-                    rcvr_ty.prefix_string(self.tcx)
-                },
-                ty_str: ty_str_reported,
-                trait_missing_method,
-            })
-        };
+        let mut err =
+            if is_write && let SelfSource::MethodCall(rcvr_expr) = source
+            {
+                self.suggest_missing_writer(rcvr_ty, rcvr_expr)
+            } else {
+                tcx.sess.create_err(NoAssociatedItem {
+                    span,
+                    item_kind,
+                    item_name,
+                    ty_prefix: if trait_missing_method {
+                        // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+                        Cow::from("trait")
+                    } else {
+                        rcvr_ty.prefix_string(self.tcx)
+                    },
+                    ty_str: ty_str_reported,
+                    trait_missing_method,
+                })
+            };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
@@ -409,6 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.downgrade_to_delayed_bug();
         }
 
+        if matches!(source, SelfSource::QPath(_)) && args.is_some() {
+            self.find_builder_fn(&mut err, rcvr_ty);
+        }
+
         if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
             err.help(format!(
                 "method `poll` found on `Pin<&mut {ty_str}>`, \
@@ -522,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.note_candidates_on_method_error(
                 rcvr_ty,
                 item_name,
+                source,
                 args,
                 span,
                 &mut err,
@@ -532,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.note_candidates_on_method_error(
                 rcvr_ty,
                 item_name,
+                source,
                 args,
                 span,
                 &mut err,
@@ -975,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 unsatisfied_bounds = true;
             }
         } else if let ty::Adt(def, targs) = rcvr_ty.kind()
-            && let Some(args) = args
+            && let SelfSource::MethodCall(rcvr_expr) = source
         {
             // This is useful for methods on arbitrary self types that might have a simple
             // mutability difference, like calling a method on `Pin<&mut Self>` that is on
@@ -998,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         rcvr_ty,
                         &item_segment,
                         span,
-                        args.full_expr,
-                        args.receiver,
+                        tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(),
+                        rcvr_expr,
                     ) {
                         err.span_note(
                             tcx.def_span(method.def_id),
@@ -1168,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 rcvr_ty,
                 item_name,
-                args.map(|MethodCallComponents { args, .. }| args.len() + 1),
+                args.map(|args| args.len() + 1),
                 source,
                 no_match_data.out_of_scope_traits.clone(),
                 &unsatisfied_predicates,
@@ -1249,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
-        args: Option<MethodCallComponents<'tcx>>,
+        self_source: SelfSource<'tcx>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         span: Span,
         err: &mut Diagnostic,
         sources: &mut Vec<CandidateSource>,
@@ -1319,38 +1320,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     if let Some(sugg_span) = sugg_span
                         && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did)
-                    {
-                        let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
-
-                        let ty = match item.kind {
-                            ty::AssocKind::Const | ty::AssocKind::Type => impl_ty,
-                            ty::AssocKind::Fn => self
-                                .tcx
-                                .fn_sig(item.def_id)
-                                .instantiate_identity()
-                                .inputs()
-                                .skip_binder()
-                                .get(0)
-                                .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref())
-                                .copied()
-                                .unwrap_or(rcvr_ty),
-                        };
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            ty,
-                            Some(impl_ty),
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            trait_ref.instantiate(
+                                self.tcx,
+                                self.fresh_args_for_item(sugg_span, impl_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
                 CandidateSource::Trait(trait_did) => {
@@ -1372,24 +1356,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_note(item_span, msg);
                         None
                     };
-                    if let Some(sugg_span) = sugg_span {
-                        let path = self.tcx.def_path_str(trait_did);
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
+                    if let Some(sugg_span) = sugg_span
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            rcvr_ty,
-                            None,
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            ty::TraitRef::new(
+                                self.tcx,
+                                trait_did,
+                                self.fresh_args_for_item(sugg_span, trait_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
             }
@@ -1407,6 +1390,85 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Look at all the associated functions without receivers in the type's inherent impls
+    /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
+    fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) {
+        let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
+            return;
+        };
+        let mut items = self
+            .tcx
+            .inherent_impls(adt_def.did())
+            .iter()
+            .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
+            // Only assoc fn with no receivers.
+            .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter)
+            .filter_map(|item| {
+                // Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
+                let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output();
+                let ret_ty = self.tcx.erase_late_bound_regions(ret_ty);
+                let ty::Adt(def, args) = ret_ty.kind() else {
+                    return None;
+                };
+                // Check for `-> Self`
+                if self.can_eq(self.param_env, ret_ty, rcvr_ty) {
+                    return Some((item.def_id, ret_ty));
+                }
+                // Check for `-> Option<Self>` or `-> Result<Self, _>`
+                if ![self.tcx.lang_items().option_type(), self.tcx.get_diagnostic_item(sym::Result)]
+                    .contains(&Some(def.did()))
+                {
+                    return None;
+                }
+                let arg = args.get(0)?.expect_ty();
+                if self.can_eq(self.param_env, rcvr_ty, arg) {
+                    Some((item.def_id, ret_ty))
+                } else {
+                    None
+                }
+            })
+            .collect::<Vec<_>>();
+        let post = if items.len() > 5 {
+            let items_len = items.len();
+            items.truncate(4);
+            format!("\nand {} others", items_len - 4)
+        } else {
+            String::new()
+        };
+        match &items[..] {
+            [] => {}
+            [(def_id, ret_ty)] => {
+                err.span_note(
+                    self.tcx.def_span(def_id),
+                    format!(
+                        "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \
+                         returns `{ret_ty}`",
+                        self.tcx.def_path_str(def_id),
+                    ),
+                );
+            }
+            _ => {
+                let span: MultiSpan = items
+                    .iter()
+                    .map(|(def_id, _)| self.tcx.def_span(def_id))
+                    .collect::<Vec<Span>>()
+                    .into();
+                err.span_note(
+                    span,
+                    format!(
+                        "if you're trying to build a new `{rcvr_ty}` consider using one of the \
+                         following associated functions:\n{}{post}",
+                        items
+                            .iter()
+                            .map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id))
+                            .collect::<Vec<String>>()
+                            .join("\n")
+                    ),
+                );
+            }
+        }
+    }
+
     /// Suggest calling `Ty::method` if `.method()` isn't found because the method
     /// doesn't take a `self` receiver.
     fn suggest_associated_call_syntax(
@@ -1416,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         source: SelfSource<'tcx>,
         item_name: Ident,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         sugg_span: Span,
     ) {
         let mut has_unsuggestable_args = false;
@@ -1490,38 +1552,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 None
             };
             let mut applicability = Applicability::MachineApplicable;
-            let args = if let Some(MethodCallComponents { receiver, args, .. }) = args {
-                // The first arg is the same kind as the receiver
-                let explicit_args = if first_arg.is_some() {
-                    std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
+            let args = if let SelfSource::MethodCall(receiver) = source
+                    && let Some(args) = args
+                {
+                    // The first arg is the same kind as the receiver
+                    let explicit_args = if first_arg.is_some() {
+                        std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
+                    } else {
+                        // There is no `Self` kind to infer the arguments from
+                        if has_unsuggestable_args {
+                            applicability = Applicability::HasPlaceholders;
+                        }
+                        args.iter().collect()
+                    };
+                    format!(
+                        "({}{})",
+                        first_arg.unwrap_or(""),
+                        explicit_args
+                            .iter()
+                            .map(|arg| self
+                                .tcx
+                                .sess
+                                .source_map()
+                                .span_to_snippet(arg.span)
+                                .unwrap_or_else(|_| {
+                                    applicability = Applicability::HasPlaceholders;
+                                    "_".to_owned()
+                                }))
+                            .collect::<Vec<_>>()
+                            .join(", "),
+                    )
                 } else {
-                    // There is no `Self` kind to infer the arguments from
-                    if has_unsuggestable_args {
-                        applicability = Applicability::HasPlaceholders;
-                    }
-                    args.iter().collect()
+                    applicability = Applicability::HasPlaceholders;
+                    "(...)".to_owned()
                 };
-                format!(
-                    "({}{})",
-                    first_arg.unwrap_or(""),
-                    explicit_args
-                        .iter()
-                        .map(|arg| self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(arg.span)
-                            .unwrap_or_else(|_| {
-                                applicability = Applicability::HasPlaceholders;
-                                "_".to_owned()
-                            }))
-                        .collect::<Vec<_>>()
-                        .join(", "),
-                )
-            } else {
-                applicability = Applicability::HasPlaceholders;
-                "(...)".to_owned()
-            };
             err.span_suggestion(
                 sugg_span,
                 "use associated function syntax instead",
@@ -3179,56 +3243,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 }
 
 fn print_disambiguation_help<'tcx>(
-    item_name: Ident,
-    args: Option<MethodCallComponents<'tcx>>,
+    tcx: TyCtxt<'tcx>,
     err: &mut Diagnostic,
-    trait_name: String,
-    rcvr_ty: Ty<'_>,
-    impl_self_ty: Option<Ty<'_>>,
-    kind: ty::AssocKind,
-    def_kind_descr: &'static str,
+    source: SelfSource<'tcx>,
+    args: Option<&'tcx [hir::Expr<'tcx>]>,
+    trait_ref: ty::TraitRef<'tcx>,
+    candidate_idx: Option<usize>,
     span: Span,
-    candidate: Option<usize>,
-    source_map: &source_map::SourceMap,
-    fn_has_self_parameter: bool,
+    item: ty::AssocItem,
 ) -> Option<String> {
+    let trait_ref = if item.fn_has_self_parameter {
+        trait_ref.print_only_trait_name().to_string()
+    } else {
+        format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
+    };
     Some(
-        if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args)
+        if matches!(item.kind, ty::AssocKind::Fn)
+            && let SelfSource::MethodCall(receiver) = source
+            && let Some(args) = args
         {
+            let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
+            let item_name = item.ident(tcx);
+            let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
+                .ref_mutability()
+                .map_or("", |mutbl| mutbl.ref_prefix_str());
             let args = format!(
                 "({}{})",
-                rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
+                rcvr_ref,
                 std::iter::once(receiver)
                     .chain(args.iter())
-                    .map(|arg| source_map
+                    .map(|arg| tcx
+                        .sess
+                        .source_map()
                         .span_to_snippet(arg.span)
                         .unwrap_or_else(|_| { "_".to_owned() }))
                     .collect::<Vec<_>>()
                     .join(", "),
             );
-            let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>")
-        } else {
-            trait_name
-        };
             err.span_suggestion_verbose(
                 span,
                 format!(
                     "disambiguate the {def_kind_descr} for {}",
-                    if let Some(candidate) = candidate {
+                    if let Some(candidate) = candidate_idx {
                         format!("candidate #{candidate}")
                     } else {
                         "the candidate".to_string()
                     },
                 ),
-                format!("{trait_name}::{item_name}{args}"),
+                format!("{trait_ref}::{item_name}{args}"),
                 Applicability::HasPlaceholders,
             );
             return None;
-        } else if let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>::")
         } else {
-            format!("{trait_name}::")
+            format!("{trait_ref}::")
         },
     )
 }
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index d0d3b0e5b73..f40406c6726 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -379,6 +379,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         (err, output_def_id)
                     }
                 };
+                if self.check_for_missing_semi(expr, &mut err)
+                    && let hir::Node::Expr(expr) = self.tcx.hir().get_parent(expr.hir_id)
+                    && let hir::ExprKind::Assign(..) = expr.kind
+                {
+                    // We defer to the later error produced by `check_lhs_assignable`.
+                    err.delay_as_bug();
+                }
 
                 let suggest_deref_binop =
                     |err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 50684482c0d..b30f9b82fbb 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
         let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
         let path_res = match &pat.kind {
-            PatKind::Path(qpath) => {
-                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
-            }
+            PatKind::Path(qpath) => Some(
+                self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
+            ),
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Resolve the path and check the definition for errors.
         let (res, opt_ty, segments) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
+            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
         if res == Res::Err {
             let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
             self.set_tainted_by_errors(e);
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 75c70ec59fb..17b81acd506 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 origin = updated.1;
 
                 let (place, capture_kind) = match capture_clause {
-                    hir::CaptureBy::Value => adjust_for_move_closure(place, capture_kind),
+                    hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind),
                     hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind),
                 };
 
@@ -958,7 +958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
         let ty = match closure_clause {
-            hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value
+            hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value
             hir::CaptureBy::Ref => {
                 // For non move closure the capture kind is the max capture kind of all captures
                 // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
@@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             match closure_clause {
                 // Only migrate if closure is a move closure
-                hir::CaptureBy::Value => {
+                hir::CaptureBy::Value { .. } => {
                     let mut diagnostics_info = FxIndexSet::default();
                     let upvars =
                         self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
@@ -1479,10 +1479,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If the data will be moved out of this place, then the place will be truncated
             // at the first Deref in `adjust_upvar_borrow_kind_for_consume` and then moved into
             // the closure.
-            hir::CaptureBy::Value if !place.deref_tys().any(Ty::is_ref) => {
+            hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => {
                 ty::UpvarCapture::ByValue
             }
-            hir::CaptureBy::Value | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow),
+            hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => {
+                ty::UpvarCapture::ByRef(ty::ImmBorrow)
+            }
         }
     }
 
diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl
index 5d885e07192..e74173b24a9 100644
--- a/compiler/rustc_incremental/messages.ftl
+++ b/compiler/rustc_incremental/messages.ftl
@@ -30,8 +30,6 @@ incremental_create_lock =
     incremental compilation: could not create session directory lock file: {$lock_err}
 incremental_create_new = failed to create {$name} at `{$path}`: {$err}
 
-incremental_decode_incr_cache = could not decode incremental cache: {$err}
-
 incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
 
 incremental_delete_incompatible =
diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs
index 05ed4f7598d..61bb0353a9f 100644
--- a/compiler/rustc_incremental/src/errors.rs
+++ b/compiler/rustc_incremental/src/errors.rs
@@ -271,12 +271,6 @@ pub struct LoadDepGraph {
 }
 
 #[derive(Diagnostic)]
-#[diag(incremental_decode_incr_cache)]
-pub struct DecodeIncrCache {
-    pub err: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(incremental_write_dep_graph)]
 pub struct WriteDepGraph<'a> {
     pub path: &'a Path,
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index cbd55fe4205..6dfc4096910 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -30,8 +30,6 @@ pub enum LoadResult<T> {
     DataOutOfDate,
     /// Loading the dep graph failed.
     LoadDepGraph(PathBuf, std::io::Error),
-    /// Decoding loaded incremental cache failed.
-    DecodeIncrCache(Box<dyn std::any::Any + Send>),
 }
 
 impl<T: Default> LoadResult<T> {
@@ -44,9 +42,7 @@ impl<T: Default> LoadResult<T> {
             }
             (
                 Some(IncrementalStateAssertion::Loaded),
-                LoadResult::LoadDepGraph(..)
-                | LoadResult::DecodeIncrCache(..)
-                | LoadResult::DataOutOfDate,
+                LoadResult::LoadDepGraph(..) | LoadResult::DataOutOfDate,
             ) => {
                 sess.emit_fatal(errors::AssertLoaded);
             }
@@ -58,10 +54,6 @@ impl<T: Default> LoadResult<T> {
                 sess.emit_warning(errors::LoadDepGraph { path, err });
                 Default::default()
             }
-            LoadResult::DecodeIncrCache(err) => {
-                sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") });
-                Default::default()
-            }
             LoadResult::DataOutOfDate => {
                 if let Err(err) = delete_all_session_dir_contents(sess) {
                     sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err });
@@ -150,7 +142,6 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProduct
     match load_data(&path, sess) {
         LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
         LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
-        LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
         LoadResult::Ok { data: (bytes, start_pos) } => {
             let mut decoder = MemDecoder::new(&bytes, start_pos);
             let prev_commandline_args_hash = u64::decode(&mut decoder);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index e4be435fded..26d071a0139 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2444,18 +2444,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let suggestion =
                     if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
                 suggs.push((sp, suggestion))
-            } else {
-                let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap();
+            } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) {
                 let pred = format!("{bound_kind}: {lt_name}");
-                let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,);
+                let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred);
                 suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
+            } else {
+                let consider = format!("{msg} `{bound_kind}: {sub}`...");
+                err.help(consider);
             }
 
-            err.multipart_suggestion_verbose(
-                format!("{msg}"),
-                suggs,
-                Applicability::MaybeIncorrect, // Issue #41966
-            );
+            if !suggs.is_empty() {
+                err.multipart_suggestion_verbose(
+                    format!("{msg}"),
+                    suggs,
+                    Applicability::MaybeIncorrect, // Issue #41966
+                );
+            }
         }
 
         err
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 8e66083a390..d3081695523 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -4,11 +4,11 @@ use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
 use rustc_session::config::{
     build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
-    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input,
-    InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
-    MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
-    Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
-    TraitSolver, WasiExecModel,
+    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
+    InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained,
+    LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, OomStrategy, Options, OutFileName,
+    OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip,
+    SwitchWithOptPath, SymbolManglingVersion, TraitSolver, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -748,7 +748,7 @@ fn test_unstable_options_tracking_hash() {
     );
     tracked!(codegen_backend, Some("abc".to_string()));
     tracked!(crate_attr, vec!["abc".to_string()]);
-    tracked!(cross_crate_inline_threshold, Some(200));
+    tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
     tracked!(debug_info_for_profiling, true);
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 3f2bf2c9b44..142384e6d0c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -25,7 +25,6 @@
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Vectorize.h"
 
 #define LLVM_VERSION_GE(major, minor)                                          \
   (LLVM_VERSION_MAJOR > (major) ||                                             \
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index ba75517d7a6..047066ac681 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -5,11 +5,16 @@ use syn::spanned::Spanned;
 
 pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     let decoder_ty = quote! { __D };
-    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
-        s.add_impl_generic(parse_quote! { 'tcx });
-    }
-    s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder<I = ::rustc_middle::ty::TyCtxt<'tcx>>});
-    s.add_bounds(synstructure::AddBounds::Generics);
+    let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
+    } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        quote! { <I = I> }
+    } else {
+        quote! {}
+    };
+
+    s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound });
+    s.add_bounds(synstructure::AddBounds::Fields);
 
     decodable_body(s, decoder_ty)
 }
@@ -97,12 +102,17 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream {
 }
 
 pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
-    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
-        s.add_impl_generic(parse_quote! {'tcx});
-    }
+    let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
+    } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        quote! { <I = I> }
+    } else {
+        quote! {}
+    };
+
     let encoder_ty = quote! { __E };
-    s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder<I = ::rustc_middle::ty::TyCtxt<'tcx>>});
-    s.add_bounds(synstructure::AddBounds::Generics);
+    s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound });
+    s.add_bounds(synstructure::AddBounds::Fields);
 
     encodable_body(s, encoder_ty, false)
 }
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index ec2517b581e..b06b4fb87cd 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -8,6 +8,7 @@
 #![cfg_attr(not(bootstrap), feature(coroutines))]
 #![feature(iter_from_coroutine)]
 #![feature(let_chains)]
+#![feature(if_let_guard)]
 #![feature(proc_macro_internals)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index de436c16ca9..2042863d189 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2386,31 +2386,32 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String {
         }
     }
 
-    let classification = classify(value);
-
-    if classification == Literal
-        && !value.span.from_expansion()
-        && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span)
-    {
-        // For literals, we avoid invoking the pretty-printer and use the source snippet instead to
-        // preserve certain stylistic choices the user likely made for the sake legibility like
+    match classify(value) {
+        // For non-macro literals, we avoid invoking the pretty-printer and use the source snippet
+        // instead to preserve certain stylistic choices the user likely made for the sake of
+        // legibility, like:
         //
         // * hexadecimal notation
         // * underscores
         // * character escapes
         //
         // FIXME: This passes through `-/*spacer*/0` verbatim.
-        snippet
-    } else if classification == Simple {
+        Literal if !value.span.from_expansion()
+            && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) => {
+            snippet
+        }
+
         // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
         // other formatting artifacts.
-        id_to_string(&hir, body.hir_id)
-    } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
+        Literal | Simple => id_to_string(&hir, body.hir_id),
+
         // FIXME: Omit the curly braces if the enclosing expression is an array literal
         //        with a repeated element (an `ExprKind::Repeat`) as in such case it
         //        would not actually need any disambiguation.
-        "{ _ }".to_owned()
-    } else {
-        "_".to_owned()
+        Complex => if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
+            "{ _ }".to_owned()
+        } else {
+            "_".to_owned()
+        }
     }
 }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 0b5426c3bb1..64b63f4c5eb 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -222,7 +222,7 @@ pub enum CanonicalVarKind<'tcx> {
     Effect,
 
     /// A "placeholder" that represents "any const".
-    PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>),
+    PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>),
 }
 
 impl<'tcx> CanonicalVarKind<'tcx> {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index e20e9d9312c..cdde6a596a8 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -2,7 +2,8 @@ use crate::mir;
 use crate::query::CyclePlaceholder;
 use crate::traits;
 use crate::ty::{self, Ty};
-use std::mem::{size_of, transmute_copy, MaybeUninit};
+use std::intrinsics::transmute_unchecked;
+use std::mem::{size_of, MaybeUninit};
 
 #[derive(Copy, Clone)]
 pub struct Erased<T: Copy> {
@@ -29,8 +30,15 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     };
 
     Erased::<<T as EraseType>::Result> {
+        // `transmute_unchecked` is needed here because it does not have `transmute`'s size check
+        // (and thus allows to transmute between `T` and `MaybeUninit<T::Result>`) (we do the size
+        // check ourselves in the `const` block above).
+        //
+        // `transmute_copy` is also commonly used for this (and it would work here since
+        // `EraseType: Copy`), but `transmute_unchecked` better explains the intent.
+        //
         // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
-        data: unsafe { transmute_copy(&src) },
+        data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Result>>(src) },
     }
 }
 
@@ -38,22 +46,24 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
 #[inline(always)]
 pub fn restore<T: EraseType>(value: Erase<T>) -> T {
     let value: Erased<<T as EraseType>::Result> = value;
+    // See comment in `erase` for why we use `transmute_unchecked`.
+    //
     // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
     // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
     // the right size.
-    unsafe { transmute_copy(&value.data) }
+    unsafe { transmute_unchecked::<MaybeUninit<T::Result>, T>(value.data) }
 }
 
 impl<T> EraseType for &'_ T {
-    type Result = [u8; size_of::<*const ()>()];
+    type Result = [u8; size_of::<&'static ()>()];
 }
 
 impl<T> EraseType for &'_ [T] {
-    type Result = [u8; size_of::<*const [()]>()];
+    type Result = [u8; size_of::<&'static [()]>()];
 }
 
 impl<T> EraseType for &'_ ty::List<T> {
-    type Result = [u8; size_of::<*const ()>()];
+    type Result = [u8; size_of::<&'static ty::List<()>>()];
 }
 
 impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index d03d92c3a4b..8feefb4c03c 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
         Use { source } => visitor.visit_expr(&visitor.thir()[source]),
         NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
         PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
-        Let { expr, .. } => {
+        Let { expr, ref pat } => {
             visitor.visit_expr(&visitor.thir()[expr]);
+            visitor.visit_pat(pat);
         }
         Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
         Match { scrutinee, ref arms, .. } => {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 9e2ff3820af..6cd75e08727 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -305,9 +305,14 @@ pub enum ObligationCauseCode<'tcx> {
     SizedCoroutineInterior(LocalDefId),
     /// `[expr; N]` requires `type_of(expr): Copy`.
     RepeatElementCopy {
-        /// If element is a `const fn` we display a help message suggesting to move the
-        /// function call to a new `const` item while saying that `T` doesn't implement `Copy`.
-        is_const_fn: bool,
+        /// If element is a `const fn` or const ctor we display a help message suggesting
+        /// to move it to a new `const` item while saying that `T` doesn't implement `Copy`.
+        is_constable: IsConstable,
+        elt_type: Ty<'tcx>,
+        elt_span: Span,
+        /// Span of the statement/item in which the repeat expression occurs. We can use this to
+        /// place a `const` declaration before it
+        elt_stmt_span: Span,
     },
 
     /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
@@ -455,6 +460,21 @@ pub enum ObligationCauseCode<'tcx> {
     TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
 }
 
+/// Whether a value can be extracted into a const.
+/// Used for diagnostics around array repeat expressions.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum IsConstable {
+    No,
+    /// Call to a const fn
+    Fn,
+    /// Use of a const ctor
+    Ctor,
+}
+
+crate::TrivialTypeTraversalAndLiftImpls! {
+    IsConstable,
+}
+
 /// The 'location' at which we try to perform HIR-based wf checking.
 /// This information is used to obtain an `hir::Ty`, which
 /// we can walk in order to obtain precise spans for any
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index cfacccd2679..af5ffc20d48 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     pub fn new_placeholder(
         tcx: TyCtxt<'tcx>,
-        placeholder: ty::PlaceholderConst<'tcx>,
+        placeholder: ty::PlaceholderConst,
         ty: Ty<'tcx>,
     ) -> Const<'tcx> {
         Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 68812bba42f..551c4a15dd0 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type Const = ty::Const<'tcx>;
     type InferConst = ty::InferConst;
     type AliasConst = ty::UnevaluatedConst<'tcx>;
-    type PlaceholderConst = ty::PlaceholderConst<'tcx>;
+    type PlaceholderConst = ty::PlaceholderConst;
     type ParamConst = ty::ParamConst;
     type BoundConst = ty::BoundVar;
     type ValueConst = ty::ValTree<'tcx>;
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 77a50fa9276..0094825fc70 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -274,7 +274,7 @@ pub fn suggest_constraining_type_params<'a>(
                 span,
                 if span_to_replace.is_some() {
                     constraint.clone()
-                } else if constraint.starts_with("<") {
+                } else if constraint.starts_with('<') {
                     constraint.to_string()
                 } else if bound_list_non_empty {
                     format!(" + {constraint}")
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 7895993ccff..3371ea3bec8 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        // If there's nothing to erase avoid performing the query at all
-        if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+        // If there's nothing to erase or anonymize, avoid performing the query at all
+        if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
             return value;
         }
         debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index a348e9f608a..ec36bdc5a51 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,26 +34,6 @@ impl FlagComputation {
         result.flags
     }
 
-    pub fn bound_var_flags(vars: &ty::List<ty::BoundVariableKind>) -> FlagComputation {
-        let mut computation = FlagComputation::new();
-
-        for bv in vars {
-            match bv {
-                ty::BoundVariableKind::Ty(_) => {
-                    computation.flags |= TypeFlags::HAS_TY_LATE_BOUND;
-                }
-                ty::BoundVariableKind::Region(_) => {
-                    computation.flags |= TypeFlags::HAS_RE_LATE_BOUND;
-                }
-                ty::BoundVariableKind::Const => {
-                    computation.flags |= TypeFlags::HAS_CT_LATE_BOUND;
-                }
-            }
-        }
-
-        computation
-    }
-
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | flags;
     }
@@ -77,7 +57,11 @@ impl FlagComputation {
     where
         F: FnOnce(&mut Self, T),
     {
-        let mut computation = FlagComputation::bound_var_flags(value.bound_vars());
+        let mut computation = FlagComputation::new();
+
+        if !value.bound_vars().is_empty() {
+            computation.add_flags(TypeFlags::HAS_BINDER_VARS);
+        }
 
         f(&mut computation, value.skip_binder());
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 739d4fa886e..e1c616ba078 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1527,7 +1527,7 @@ pub struct BoundConst<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
+pub type PlaceholderConst = Placeholder<BoundVar>;
 
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
@@ -2011,7 +2011,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // Generate a deterministically-derived seed from the item's path hash
         // to allow for cross-crate compilation to actually work
-        let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash();
+        let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash().as_u64();
 
         // If the user defined a custom seed for layout randomization, xor the item's
         // path hash with the user defined seed, this will allowing determinism while
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index ab0999b3f19..8fc5c030277 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
         &mut self,
         t: &Binder<'tcx, T>,
     ) -> ControlFlow<Self::BreakTy> {
-        // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to
-        // additionally consider the bound vars on the binder itself, even if
-        // the contents of a the binder (e.g. a `TraitRef`) doesn't reference
-        // the bound vars.
-        if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) {
-            let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars());
-            if bound_var_flags.flags.intersects(self.flags) {
-                return ControlFlow::Break(FoundFlags);
-            }
+        // If we're looking for the HAS_BINDER_VARS flag, check if the
+        // binder has vars. This won't be present in the binder's bound
+        // value, so we need to check here too.
+        if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
+            return ControlFlow::Break(FoundFlags);
         }
 
         t.super_visit_with(self)
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 32711c23dc4..54fc8f77f93 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -221,6 +221,11 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici
     .help = ensure that all variants are matched explicitly by adding the suggested match arms
     .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
 
+mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match
+    .help = it no longer has any effect to set the lint level on an individual match arm
+    .label = remove this attribute
+    .suggestion = set the lint level on the whole match
+
 mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
     .def_note = `{$peeled_ty}` defined here
     .type_note = the matched value is of type `{$ty}`
@@ -315,6 +320,7 @@ mir_build_unreachable_pattern = unreachable pattern
     .label = unreachable pattern
     .catchall_label = matches any value
 
+mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default
 mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items
 
 mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
@@ -381,3 +387,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block
 mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
 
 mir_build_variant_defined_here = not covered
+
+mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index c3e1b55e463..a43aae6f449 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -856,7 +856,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
 
             PatKind::InlineConstant { ref subpattern, .. } => {
-                self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f)
+                self.visit_primary_bindings(subpattern, pattern_user_ty, f)
             }
 
             PatKind::Leaf { ref subpatterns } => {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 58d6be50b90..7c729016521 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -620,29 +620,63 @@ fn construct_const<'a, 'tcx>(
 ///
 /// This is required because we may still want to run MIR passes on an item
 /// with type errors, but normal MIR construction can't handle that in general.
-fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
-    let span = tcx.def_span(def);
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def);
-    let coroutine_kind = tcx.coroutine_kind(def);
-    let body_owner_kind = tcx.hir().body_owner_kind(def);
-
-    let ty = Ty::new_error(tcx, err);
-    let num_params = match body_owner_kind {
-        hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
-        hir::BodyOwnerKind::Closure => {
-            let ty = tcx.type_of(def).instantiate_identity();
-            match ty.kind() {
-                ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(),
-                ty::Coroutine(..) => 2,
-                _ => bug!("expected closure or coroutine, found {ty:?}"),
-            }
+fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> {
+    let span = tcx.def_span(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+    let coroutine_kind = tcx.coroutine_kind(def_id);
+
+    let (inputs, output, yield_ty) = match tcx.def_kind(def_id) {
+        DefKind::Const
+        | DefKind::AssocConst
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
+        DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
+            let sig = tcx.liberate_late_bound_regions(
+                def_id.to_def_id(),
+                tcx.fn_sig(def_id).instantiate_identity(),
+            );
+            (sig.inputs().to_vec(), sig.output(), None)
+        }
+        DefKind::Closure => {
+            let closure_ty = tcx.type_of(def_id).instantiate_identity();
+            let ty::Closure(_, args) = closure_ty.kind() else { bug!() };
+            let args = args.as_closure();
+            let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
+            let self_ty = match args.kind() {
+                ty::ClosureKind::Fn => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
+                ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
+                ty::ClosureKind::FnOnce => closure_ty,
+            };
+            ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None)
+        }
+        DefKind::Coroutine => {
+            let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
+            let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() };
+            let args = args.as_coroutine();
+            let yield_ty = args.yield_ty();
+            let return_ty = args.return_ty();
+            let self_ty = Ty::new_adt(
+                tcx,
+                tcx.adt_def(tcx.lang_items().pin_type().unwrap()),
+                tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]),
+            );
+            let coroutine_state = Ty::new_adt(
+                tcx,
+                tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()),
+                tcx.mk_args(&[yield_ty.into(), return_ty.into()]),
+            );
+            (vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty))
         }
-        hir::BodyOwnerKind::Const { .. } => 0,
-        hir::BodyOwnerKind::Static(_) => 0,
+        dk => bug!("{:?} is not a body: {:?}", def_id, dk),
     };
+
+    let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
+    let local_decls = IndexVec::from_iter(
+        [output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)),
+    );
     let mut cfg = CFG { basic_blocks: IndexVec::new() };
     let mut source_scopes = IndexVec::new();
-    let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
 
     cfg.start_new_block();
     source_scopes.push(SourceScopeData {
@@ -655,28 +689,24 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
             safety: Safety::Safe,
         }),
     });
-    let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
 
-    // Some MIR passes will expect the number of parameters to match the
-    // function declaration.
-    for _ in 0..num_params {
-        local_decls.push(LocalDecl::with_source_info(ty, source_info));
-    }
     cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
 
     let mut body = Body::new(
-        MirSource::item(def.to_def_id()),
+        MirSource::item(def_id.to_def_id()),
         cfg.basic_blocks,
         source_scopes,
         local_decls,
         IndexVec::new(),
-        num_params,
+        inputs.len(),
         vec![],
         span,
         coroutine_kind,
-        Some(err),
+        Some(guar),
     );
-    body.coroutine.as_mut().map(|gen| gen.yield_ty = Some(ty));
+
+    body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty);
+
     body
 }
 
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 45be5015371..3d895c131a8 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> {
     param_env: ParamEnv<'tcx>,
     inside_adt: bool,
     warnings: &'a mut Vec<UnusedUnsafeWarning>,
+
+    /// Flag to ensure that we only suggest wrapping the entire function body in
+    /// an unsafe block once.
+    suggest_unsafe_block: bool,
 }
 
 impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
                 // unsafe_op_in_unsafe_fn is disallowed
-                kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
+                kind.emit_unsafe_op_in_unsafe_fn_lint(
+                    self.tcx,
+                    self.hir_context,
+                    span,
+                    self.suggest_unsafe_block,
+                );
+                self.suggest_unsafe_block = false;
             }
             SafetyContext::Safe => {
                 kind.emit_requires_unsafe_err(
@@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             }
             PatKind::InlineConstant { def, .. } => {
                 self.visit_inner_body(*def);
+                visit::walk_pat(self, pat);
             }
             _ => {
                 visit::walk_pat(self, pat);
@@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 }
             }
             ExprKind::Deref { arg } => {
-                if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind {
+                if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
+                    self.thir[arg].kind
+                {
                     if self.tcx.is_mutable_static(def_id) {
                         self.requires_unsafe(expr.span, UseOfMutableStatic);
                     } else if self.tcx.is_foreign_item(def_id) {
@@ -482,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     }
                 }
             }
-            ExprKind::Let { expr: expr_id, .. } => {
-                let let_expr = &self.thir[expr_id];
-                if let ty::Adt(adt_def, _) = let_expr.ty.kind()
-                    && adt_def.is_union()
-                {
-                    self.requires_unsafe(expr.span, AccessToUnionField);
-                }
-            }
             _ => {}
         }
         visit::walk_expr(self, expr);
@@ -543,7 +548,22 @@ impl UnsafeOpKind {
         tcx: TyCtxt<'_>,
         hir_id: hir::HirId,
         span: Span,
+        suggest_unsafe_block: bool,
     ) {
+        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_owner = tcx.hir().owner(parent_id);
+        let should_suggest = parent_owner.fn_sig().map_or(false, |sig| sig.header.is_unsafe());
+        let unsafe_not_inherited_note = if should_suggest {
+            suggest_unsafe_block.then(|| {
+                let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span;
+                UnsafeNotInheritedLintNote {
+                    signature_span: tcx.def_span(parent_id.def_id),
+                    body_span,
+                }
+            })
+        } else {
+            None
+        };
         // FIXME: ideally we would want to trim the def paths, but this is not
         // feasible with the current lint emission API (see issue #106126).
         match self {
@@ -554,61 +574,89 @@ impl UnsafeOpKind {
                 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
                     span,
                     function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
+                    unsafe_not_inherited_note,
                 },
             ),
             CallToUnsafeFunction(None) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
+                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfInlineAssembly => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             InitializingTypeWith => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfMutableStatic => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfExternStatic => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             DerefOfRawPointer => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             AccessToUnionField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             CallToFunctionWith(did) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
@@ -617,6 +665,7 @@ impl UnsafeOpKind {
                 UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
                     span,
                     function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
+                    unsafe_not_inherited_note,
                 },
             ),
         }
@@ -831,6 +880,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
         param_env: tcx.param_env(def),
         inside_adt: false,
         warnings: &mut warnings,
+        suggest_unsafe_block: true,
     };
     visitor.visit_expr(&thir[expr]);
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 5bfce3ab510..418f9bb9de9 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -29,6 +29,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
     #[label]
     pub span: Span,
     pub function: &'a str,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
 pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -109,6 +129,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
     #[label]
     pub span: Span,
     pub function: &'a str,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(Diagnostic)]
@@ -376,6 +398,27 @@ pub struct UnsafeNotInheritedNote {
     pub span: Span,
 }
 
+pub struct UnsafeNotInheritedLintNote {
+    pub signature_span: Span,
+    pub body_span: Span,
+}
+
+impl AddToDiagnostic for UnsafeNotInheritedLintNote {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
+        let body_start = self.body_span.shrink_to_lo();
+        let body_end = self.body_span.shrink_to_hi();
+        diag.tool_only_multipart_suggestion(
+            fluent::mir_build_wrap_suggestion,
+            vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())],
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
+
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unused_unsafe)]
 pub struct UnusedUnsafe {
@@ -789,6 +832,18 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
     pub uncovered: Uncovered<'tcx>,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)]
+#[help]
+pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
+    #[label]
+    pub lint_span: Span,
+    #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")]
+    pub suggest_lint_on_match: Option<Span>,
+    pub lint_level: &'static str,
+    pub lint_name: &'static str,
+}
+
 #[derive(Subdiagnostic)]
 #[label(mir_build_uncovered)]
 pub(crate) struct Uncovered<'tcx> {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 933653e708e..8c3d09c19a1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -9,9 +9,7 @@ use rustc_arena::TypedArena;
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{
-    struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
-};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::LocalDefId;
@@ -44,7 +42,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
 
     for param in thir.params.iter() {
         if let Some(box ref pattern) = param.pat {
-            visitor.check_irrefutable(pattern, "function argument", None);
+            visitor.check_binding_is_irrefutable(pattern, "function argument", None);
         }
     }
     visitor.error
@@ -58,7 +56,7 @@ fn create_e0004(
     struct_span_err!(sess, sp, E0004, "{}", &error_message)
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 enum RefutableFlag {
     Irrefutable,
     Refutable,
@@ -68,24 +66,30 @@ use RefutableFlag::*;
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum LetSource {
     None,
+    PlainLet,
     IfLet,
     IfLetGuard,
     LetElse,
     WhileLet,
 }
 
-struct MatchVisitor<'a, 'p, 'tcx> {
+struct MatchVisitor<'thir, 'p, 'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    thir: &'a Thir<'tcx>,
+    thir: &'thir Thir<'tcx>,
     lint_level: HirId,
     let_source: LetSource,
     pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
+    /// Tracks if we encountered an error while checking this body. That the first function to
+    /// report it stores it here. Some functions return `Result` to allow callers to short-circuit
+    /// on error, but callers don't need to store it here again.
     error: Result<(), ErrorGuaranteed>,
 }
 
-impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
-    fn thir(&self) -> &'a Thir<'tcx> {
+// Visitor for a thir body. This calls `check_match`, `check_let` and `check_let_chain` as
+// appropriate.
+impl<'thir, 'tcx> Visitor<'thir, 'tcx> for MatchVisitor<'thir, '_, 'tcx> {
+    fn thir(&self) -> &'thir Thir<'tcx> {
         self.thir
     }
 
@@ -100,7 +104,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
                 }
                 Some(Guard::IfLet(ref pat, expr)) => {
                     this.with_let_source(LetSource::IfLetGuard, |this| {
-                        this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
+                        this.check_let(pat, Some(expr), pat.span);
                         this.visit_pat(pat);
                         this.visit_expr(&this.thir[expr]);
                     });
@@ -148,10 +152,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
                 self.check_match(scrutinee, arms, source, ex.span);
             }
             ExprKind::Let { box ref pat, expr } => {
-                self.check_let(pat, expr, self.let_source, ex.span);
+                self.check_let(pat, Some(expr), ex.span);
             }
-            ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
-                self.check_let_chain(self.let_source, ex.span, lhs, rhs);
+            ExprKind::LogicalOp { op: LogicalOp::And, .. }
+                if !matches!(self.let_source, LetSource::None) =>
+            {
+                let mut chain_refutabilities = Vec::new();
+                let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return };
+                // If at least one of the operands is a `let ... = ...`.
+                if chain_refutabilities.iter().any(|x| x.is_some()) {
+                    self.check_let_chain(chain_refutabilities, ex.span);
+                }
+                return;
             }
             _ => {}
         };
@@ -159,33 +171,27 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
     }
 
     fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
-        let old_lint_level = self.lint_level;
         match stmt.kind {
             StmtKind::Let {
                 box ref pattern, initializer, else_block, lint_level, span, ..
             } => {
-                if let LintLevel::Explicit(lint_level) = lint_level {
-                    self.lint_level = lint_level;
-                }
-
-                if let Some(initializer) = initializer
-                    && else_block.is_some()
-                {
-                    self.check_let(pattern, initializer, LetSource::LetElse, span);
-                }
-
-                if else_block.is_none() {
-                    self.check_irrefutable(pattern, "local binding", Some(span));
-                }
+                self.with_lint_level(lint_level, |this| {
+                    let let_source =
+                        if else_block.is_some() { LetSource::LetElse } else { LetSource::PlainLet };
+                    this.with_let_source(let_source, |this| {
+                        this.check_let(pattern, initializer, span)
+                    });
+                    visit::walk_stmt(this, stmt);
+                });
+            }
+            StmtKind::Expr { .. } => {
+                visit::walk_stmt(self, stmt);
             }
-            _ => {}
         }
-        visit::walk_stmt(self, stmt);
-        self.lint_level = old_lint_level;
     }
 }
 
-impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
+impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
     #[instrument(level = "trace", skip(self, f))]
     fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) {
         let old_let_source = self.let_source;
@@ -194,53 +200,127 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         self.let_source = old_let_source;
     }
 
-    fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) {
+    fn with_lint_level<T>(
+        &mut self,
+        new_lint_level: LintLevel,
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
         if let LintLevel::Explicit(hir_id) = new_lint_level {
             let old_lint_level = self.lint_level;
             self.lint_level = hir_id;
-            f(self);
+            let ret = f(self);
             self.lint_level = old_lint_level;
+            ret
         } else {
-            f(self);
+            f(self)
         }
     }
 
-    fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
-        pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
-        check_for_bindings_named_same_as_variants(self, pat, rf);
+    /// Visit a nested chain of `&&`. Used for if-let chains. This must call `visit_expr` on the
+    /// subexpressions we are not handling ourselves.
+    fn visit_land(
+        &mut self,
+        ex: &Expr<'tcx>,
+        accumulator: &mut Vec<Option<(Span, RefutableFlag)>>,
+    ) -> Result<(), ErrorGuaranteed> {
+        match ex.kind {
+            ExprKind::Scope { value, lint_level, .. } => self.with_lint_level(lint_level, |this| {
+                this.visit_land(&this.thir[value], accumulator)
+            }),
+            ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
+                // We recurse into the lhs only, because `&&` chains associate to the left.
+                let res_lhs = self.visit_land(&self.thir[lhs], accumulator);
+                let res_rhs = self.visit_land_rhs(&self.thir[rhs])?;
+                accumulator.push(res_rhs);
+                res_lhs
+            }
+            _ => {
+                let res = self.visit_land_rhs(ex)?;
+                accumulator.push(res);
+                Ok(())
+            }
+        }
+    }
+
+    /// Visit the right-hand-side of a `&&`. Used for if-let chains. Returns `Some` if the
+    /// expression was ultimately a `let ... = ...`, and `None` if it was a normal boolean
+    /// expression. This must call `visit_expr` on the subexpressions we are not handling ourselves.
+    fn visit_land_rhs(
+        &mut self,
+        ex: &Expr<'tcx>,
+    ) -> Result<Option<(Span, RefutableFlag)>, ErrorGuaranteed> {
+        match ex.kind {
+            ExprKind::Scope { value, lint_level, .. } => {
+                self.with_lint_level(lint_level, |this| this.visit_land_rhs(&this.thir[value]))
+            }
+            ExprKind::Let { box ref pat, expr } => {
+                self.with_let_source(LetSource::None, |this| {
+                    this.visit_expr(&this.thir()[expr]);
+                });
+                Ok(Some((ex.span, self.is_let_irrefutable(pat)?)))
+            }
+            _ => {
+                self.with_let_source(LetSource::None, |this| {
+                    this.visit_expr(ex);
+                });
+                Ok(None)
+            }
+        }
     }
 
     fn lower_pattern(
-        &self,
-        cx: &mut MatchCheckCtxt<'p, 'tcx>,
-        pattern: &Pat<'tcx>,
-    ) -> &'p DeconstructedPat<'p, 'tcx> {
-        cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern))
+        &mut self,
+        cx: &MatchCheckCtxt<'p, 'tcx>,
+        pat: &Pat<'tcx>,
+    ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> {
+        if let Err(err) = pat.pat_error_reported() {
+            self.error = Err(err);
+            Err(err)
+        } else {
+            // Check the pattern for some things unrelated to exhaustiveness.
+            let refutable = if cx.refutable { Refutable } else { Irrefutable };
+            pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
+            pat.walk_always(|pat| check_for_bindings_named_same_as_variants(self, pat, refutable));
+            Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat)))
+        }
     }
 
-    fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> {
+    fn new_cx(
+        &self,
+        refutability: RefutableFlag,
+        match_span: Option<Span>,
+    ) -> MatchCheckCtxt<'p, 'tcx> {
+        let refutable = match refutability {
+            Irrefutable => false,
+            Refutable => true,
+        };
         MatchCheckCtxt {
             tcx: self.tcx,
             param_env: self.param_env,
-            module: self.tcx.parent_module(hir_id).to_def_id(),
+            module: self.tcx.parent_module(self.lint_level).to_def_id(),
             pattern_arena: &self.pattern_arena,
+            match_span,
             refutable,
         }
     }
 
     #[instrument(level = "trace", skip(self))]
-    fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, span: Span) {
-        if let LetSource::None = source {
-            return;
-        }
-        if let Err(err) = pat.pat_error_reported() {
-            self.error = Err(err);
-            return;
+    fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) {
+        assert!(self.let_source != LetSource::None);
+        if let LetSource::PlainLet = self.let_source {
+            self.check_binding_is_irrefutable(pat, "local binding", Some(span))
+        } else {
+            let Ok(refutability) = self.is_let_irrefutable(pat) else { return };
+            if matches!(refutability, Irrefutable) {
+                report_irrefutable_let_patterns(
+                    self.tcx,
+                    self.lint_level,
+                    self.let_source,
+                    1,
+                    span,
+                );
+            }
         }
-        self.check_patterns(pat, Refutable);
-        let mut cx = self.new_cx(self.lint_level, true);
-        let tpat = self.lower_pattern(&mut cx, pat);
-        self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span);
     }
 
     fn check_match(
@@ -250,33 +330,22 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         source: hir::MatchSource,
         expr_span: Span,
     ) {
-        let mut cx = self.new_cx(self.lint_level, true);
+        let cx = self.new_cx(Refutable, Some(expr_span));
 
+        let mut tarms = Vec::with_capacity(arms.len());
         for &arm in arms {
-            // Check the arm for some things unrelated to exhaustiveness.
             let arm = &self.thir.arms[arm];
-            self.with_lint_level(arm.lint_level, |this| {
-                this.check_patterns(&arm.pattern, Refutable);
+            let got_error = self.with_lint_level(arm.lint_level, |this| {
+                let Ok(pat) = this.lower_pattern(&cx, &arm.pattern) else { return true };
+                let arm = MatchArm { pat, hir_id: this.lint_level, has_guard: arm.guard.is_some() };
+                tarms.push(arm);
+                false
             });
-            if let Err(err) = arm.pattern.pat_error_reported() {
-                self.error = Err(err);
+            if got_error {
                 return;
             }
         }
 
-        let tarms: Vec<_> = arms
-            .iter()
-            .map(|&arm| {
-                let arm = &self.thir.arms[arm];
-                let hir_id = match arm.lint_level {
-                    LintLevel::Explicit(hir_id) => hir_id,
-                    LintLevel::Inherited => self.lint_level,
-                };
-                let pat = self.lower_pattern(&mut cx, &arm.pattern);
-                MatchArm { pat, hir_id, has_guard: arm.guard.is_some() }
-            })
-            .collect();
-
         let scrut = &self.thir[scrut];
         let scrut_ty = scrut.ty;
         let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);
@@ -303,118 +372,37 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                 debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop));
                 let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() };
                 let [pat_field] = &subpatterns[..] else { bug!() };
-                self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None);
+                self.check_binding_is_irrefutable(&pat_field.pattern, "`for` loop binding", None);
             } else {
-                self.error = Err(non_exhaustive_match(
+                self.error = Err(report_non_exhaustive_match(
                     &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
                 ));
             }
         }
     }
 
-    fn check_let_reachability(
-        &mut self,
-        cx: &mut MatchCheckCtxt<'p, 'tcx>,
-        pat_id: HirId,
-        source: LetSource,
-        pat: &'p DeconstructedPat<'p, 'tcx>,
-        span: Span,
-    ) {
-        if is_let_irrefutable(cx, pat_id, pat) {
-            irrefutable_let_patterns(cx.tcx, pat_id, source, 1, span);
-        }
-    }
-
     #[instrument(level = "trace", skip(self))]
     fn check_let_chain(
         &mut self,
-        let_source: LetSource,
-        top_expr_span: Span,
-        mut lhs: ExprId,
-        rhs: ExprId,
+        chain_refutabilities: Vec<Option<(Span, RefutableFlag)>>,
+        whole_chain_span: Span,
     ) {
-        if let LetSource::None = let_source {
-            return;
-        }
-
-        // Lint level enclosing the next `lhs`.
-        let mut cur_lint_level = self.lint_level;
-
-        // Obtain the refutabilities of all exprs in the chain,
-        // and record chain members that aren't let exprs.
-        let mut chain_refutabilities = Vec::new();
-
-        let mut error = Ok(());
-        let mut add = |expr: ExprId, mut local_lint_level| {
-            // `local_lint_level` is the lint level enclosing the pattern inside `expr`.
-            let mut expr = &self.thir[expr];
-            debug!(?expr, ?local_lint_level, "add");
-            // Fast-forward through scopes.
-            while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
-                if let LintLevel::Explicit(hir_id) = lint_level {
-                    local_lint_level = hir_id
-                }
-                expr = &self.thir[value];
-            }
-            debug!(?expr, ?local_lint_level, "after scopes");
-            match expr.kind {
-                ExprKind::Let { box ref pat, expr: _ } => {
-                    if let Err(err) = pat.pat_error_reported() {
-                        error = Err(err);
-                        return None;
-                    }
-                    let mut ncx = self.new_cx(local_lint_level, true);
-                    let tpat = self.lower_pattern(&mut ncx, pat);
-                    let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat);
-                    Some((expr.span, refutable))
-                }
-                _ => None,
-            }
-        };
-
-        // Let chains recurse on the left, so we start by adding the rightmost.
-        chain_refutabilities.push(add(rhs, cur_lint_level));
+        assert!(self.let_source != LetSource::None);
 
-        loop {
-            while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind {
-                if let LintLevel::Explicit(hir_id) = lint_level {
-                    cur_lint_level = hir_id
-                }
-                lhs = value;
-            }
-            if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } =
-                self.thir[lhs].kind
-            {
-                chain_refutabilities.push(add(expr, cur_lint_level));
-                lhs = new_lhs;
-            } else {
-                chain_refutabilities.push(add(lhs, cur_lint_level));
-                break;
-            }
-        }
-        debug!(?chain_refutabilities);
-        chain_refutabilities.reverse();
-
-        if error.is_err() {
-            self.error = error;
-            return;
-        }
-
-        // Third, emit the actual warnings.
-        if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) {
+        if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, Irrefutable)))) {
             // The entire chain is made up of irrefutable `let` statements
-            irrefutable_let_patterns(
+            report_irrefutable_let_patterns(
                 self.tcx,
                 self.lint_level,
-                let_source,
+                self.let_source,
                 chain_refutabilities.len(),
-                top_expr_span,
+                whole_chain_span,
             );
             return;
         }
 
         if let Some(until) =
-            chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false))))
+            chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, Irrefutable))))
             && until > 0
         {
             // The chain has a non-zero prefix of irrefutable `let` statements.
@@ -425,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             // so can't always be moved out.
             // FIXME: Add checking whether the bindings are actually used in the prefix,
             // and lint if they are not.
-            if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
+            if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
                 // Emit the lint
                 let prefix = &chain_refutabilities[..until];
                 let span_start = prefix[0].unwrap().0;
@@ -442,7 +430,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         }
 
         if let Some(from) =
-            chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false))))
+            chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, Irrefutable))))
             && from != (chain_refutabilities.len() - 1)
         {
             // The chain has a non-empty suffix of irrefutable `let` statements
@@ -460,28 +448,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         }
     }
 
-    #[instrument(level = "trace", skip(self))]
-    fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
-        // If we got errors while lowering, don't emit anything more.
-        if let Err(err) = pat.pat_error_reported() {
-            self.error = Err(err);
-            return;
-        }
+    fn analyze_binding(
+        &mut self,
+        pat: &Pat<'tcx>,
+        refutability: RefutableFlag,
+    ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
+        let cx = self.new_cx(refutability, None);
+        let pat = self.lower_pattern(&cx, pat)?;
+        let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
+        let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span());
+        Ok((cx, report))
+    }
 
-        let mut cx = self.new_cx(self.lint_level, false);
+    fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result<RefutableFlag, ErrorGuaranteed> {
+        let (cx, report) = self.analyze_binding(pat, Refutable)?;
+        // Report if the pattern is unreachable, which can only occur when the type is uninhabited.
+        // This also reports unreachable sub-patterns.
+        report_arm_reachability(&cx, &report);
+        // If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
+        // irrefutable.
+        Ok(if report.non_exhaustiveness_witnesses.is_empty() { Irrefutable } else { Refutable })
+    }
 
-        let pattern = self.lower_pattern(&mut cx, pat);
-        let pattern_ty = pattern.ty();
-        let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false };
-        let report =
-            compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty, pattern.span());
+    #[instrument(level = "trace", skip(self))]
+    fn check_binding_is_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
+        let pattern_ty = pat.ty;
 
-        // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
-        // only care about exhaustiveness here.
+        let Ok((cx, report)) = self.analyze_binding(pat, Irrefutable) else { return };
         let witnesses = report.non_exhaustiveness_witnesses;
         if witnesses.is_empty() {
             // The pattern is irrefutable.
-            self.check_patterns(pat, Irrefutable);
             return;
         }
 
@@ -528,30 +524,20 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             });
         };
 
-        let adt_defined_here = try {
-            let ty = pattern_ty.peel_refs();
-            let ty::Adt(def, _) = ty.kind() else { None? };
-            let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
-            let mut variants = vec![];
-
-            for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
-                variants.push(Variant { span });
-            }
-            AdtDefinedHere { adt_def_span, ty, variants }
-        };
+        let adt_defined_here = report_adt_defined_here(self.tcx, pattern_ty, &witnesses, false);
 
         // Emit an extra note if the first uncovered witness would be uninhabited
         // if we disregard visibility.
-        let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns
+        let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns
             && let Some(witness_1) = witnesses.get(0)
             && let ty::Adt(adt, args) = witness_1.ty().kind()
             && adt.is_enum()
             && let Constructor::Variant(variant_index) = witness_1.ctor()
         {
             let variant = adt.variant(*variant_index);
-            let inhabited = variant.inhabited_predicate(cx.tcx, *adt).instantiate(cx.tcx, args);
-            assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
-            !inhabited.apply_ignore_module(cx.tcx, cx.param_env)
+            let inhabited = variant.inhabited_predicate(self.tcx, *adt).instantiate(self.tcx, args);
+            assert!(inhabited.apply(self.tcx, cx.param_env, cx.module));
+            !inhabited.apply_ignore_module(self.tcx, cx.param_env)
         } else {
             false
         };
@@ -572,70 +558,154 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
     }
 }
 
-fn check_for_bindings_named_same_as_variants(
-    cx: &MatchVisitor<'_, '_, '_>,
-    pat: &Pat<'_>,
-    rf: RefutableFlag,
-) {
-    pat.walk_always(|p| {
-        if let PatKind::Binding {
-            name,
-            mode: BindingMode::ByValue,
-            mutability: Mutability::Not,
-            subpattern: None,
-            ty,
-            ..
-        } = p.kind
-            && let ty::Adt(edef, _) = ty.peel_refs().kind()
-            && edef.is_enum()
-            && edef
-                .variants()
-                .iter()
-                .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const))
-        {
-            let variant_count = edef.variants().len();
-            let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did()));
-            cx.tcx.emit_spanned_lint(
-                BINDINGS_WITH_VARIANT_NAME,
-                cx.lint_level,
-                p.span,
-                BindingsWithVariantName {
-                    // If this is an irrefutable pattern, and there's > 1 variant,
-                    // then we can't actually match on this. Applying the below
-                    // suggestion would produce code that breaks on `check_irrefutable`.
-                    suggestion: if rf == Refutable || variant_count == 1 {
-                        Some(p.span)
-                    } else {
-                        None
-                    },
-                    ty_path,
+/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
+/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
+///
+/// For example, this would reject:
+/// - `ref x @ Some(ref mut y)`,
+/// - `ref mut x @ Some(ref y)`,
+/// - `ref mut x @ Some(ref mut y)`,
+/// - `ref mut? x @ Some(y)`, and
+/// - `x @ Some(ref mut? y)`.
+///
+/// This analysis is *not* subsumed by NLL.
+fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) {
+    // Extract `sub` in `binding @ sub`.
+    let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else {
+        return;
+    };
+
+    let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
+
+    let sess = cx.tcx.sess;
+
+    // Get the binding move, extract the mutability if by-ref.
+    let mut_outer = match mode {
+        BindingMode::ByValue if is_binding_by_move(ty) => {
+            // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
+            let mut conflicts_ref = Vec::new();
+            sub.each_binding(|_, mode, _, span| match mode {
+                BindingMode::ByValue => {}
+                BindingMode::ByRef(_) => conflicts_ref.push(span),
+            });
+            if !conflicts_ref.is_empty() {
+                sess.emit_err(BorrowOfMovedValue {
+                    binding_span: pat.span,
+                    conflicts_ref,
                     name,
-                },
-            )
+                    ty,
+                    suggest_borrowing: Some(pat.span.shrink_to_lo()),
+                });
+            }
+            return;
+        }
+        BindingMode::ByValue => return,
+        BindingMode::ByRef(m) => m.mutability(),
+    };
+
+    // We now have `ref $mut_outer binding @ sub` (semantically).
+    // Recurse into each binding in `sub` and find mutability or move conflicts.
+    let mut conflicts_move = Vec::new();
+    let mut conflicts_mut_mut = Vec::new();
+    let mut conflicts_mut_ref = Vec::new();
+    sub.each_binding(|name, mode, ty, span| {
+        match mode {
+            BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) {
+                // Both sides are `ref`.
+                (Mutability::Not, Mutability::Not) => {}
+                // 2x `ref mut`.
+                (Mutability::Mut, Mutability::Mut) => {
+                    conflicts_mut_mut.push(Conflict::Mut { span, name })
+                }
+                (Mutability::Not, Mutability::Mut) => {
+                    conflicts_mut_ref.push(Conflict::Mut { span, name })
+                }
+                (Mutability::Mut, Mutability::Not) => {
+                    conflicts_mut_ref.push(Conflict::Ref { span, name })
+                }
+            },
+            BindingMode::ByValue if is_binding_by_move(ty) => {
+                conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
+            }
+            BindingMode::ByValue => {} // `ref mut?` + by-copy is fine.
         }
     });
-}
 
-/// Checks for common cases of "catchall" patterns that may not be intended as such.
-fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
-    use Constructor::*;
-    match pat.ctor() {
-        Wildcard => true,
-        Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)),
-        _ => false,
+    let report_mut_mut = !conflicts_mut_mut.is_empty();
+    let report_mut_ref = !conflicts_mut_ref.is_empty();
+    let report_move_conflict = !conflicts_move.is_empty();
+
+    let mut occurrences = match mut_outer {
+        Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }],
+        Mutability::Not => vec![Conflict::Ref { span: pat.span, name }],
+    };
+    occurrences.extend(conflicts_mut_mut);
+    occurrences.extend(conflicts_mut_ref);
+    occurrences.extend(conflicts_move);
+
+    // Report errors if any.
+    if report_mut_mut {
+        // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
+        sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences });
+    } else if report_mut_ref {
+        // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
+        match mut_outer {
+            Mutability::Mut => {
+                sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences });
+            }
+            Mutability::Not => {
+                sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences });
+            }
+        };
+    } else if report_move_conflict {
+        // Report by-ref and by-move conflicts, e.g. `ref x @ y`.
+        sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences });
     }
 }
 
-fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
-    tcx.emit_spanned_lint(
-        UNREACHABLE_PATTERNS,
-        id,
-        span,
-        UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
-    );
+fn check_for_bindings_named_same_as_variants(
+    cx: &MatchVisitor<'_, '_, '_>,
+    pat: &Pat<'_>,
+    rf: RefutableFlag,
+) {
+    if let PatKind::Binding {
+        name,
+        mode: BindingMode::ByValue,
+        mutability: Mutability::Not,
+        subpattern: None,
+        ty,
+        ..
+    } = pat.kind
+        && let ty::Adt(edef, _) = ty.peel_refs().kind()
+        && edef.is_enum()
+        && edef
+            .variants()
+            .iter()
+            .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const))
+    {
+        let variant_count = edef.variants().len();
+        let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did()));
+        cx.tcx.emit_spanned_lint(
+            BINDINGS_WITH_VARIANT_NAME,
+            cx.lint_level,
+            pat.span,
+            BindingsWithVariantName {
+                // If this is an irrefutable pattern, and there's > 1 variant,
+                // then we can't actually match on this. Applying the below
+                // suggestion would produce code that breaks on `check_binding_is_irrefutable`.
+                suggestion: if rf == Refutable || variant_count == 1 {
+                    Some(pat.span)
+                } else {
+                    None
+                },
+                ty_path,
+                name,
+            },
+        )
+    }
 }
 
-fn irrefutable_let_patterns(
+fn report_irrefutable_let_patterns(
     tcx: TyCtxt<'_>,
     id: HirId,
     source: LetSource,
@@ -649,7 +719,7 @@ fn irrefutable_let_patterns(
     }
 
     match source {
-        LetSource::None => bug!(),
+        LetSource::None | LetSource::PlainLet => bug!(),
         LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
         LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
         LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
@@ -657,34 +727,28 @@ fn irrefutable_let_patterns(
     }
 }
 
-fn is_let_irrefutable<'p, 'tcx>(
-    cx: &mut MatchCheckCtxt<'p, 'tcx>,
-    pat_id: HirId,
-    pat: &'p DeconstructedPat<'p, 'tcx>,
-) -> bool {
-    let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
-    let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty(), pat.span());
-
-    // Report if the pattern is unreachable, which can only occur when the type is uninhabited.
-    // This also reports unreachable sub-patterns though, so we can't just replace it with an
-    // `is_uninhabited` check.
-    report_arm_reachability(&cx, &report);
-
-    // If the list of witnesses is empty, the match is exhaustive,
-    // i.e. the `if let` pattern is irrefutable.
-    report.non_exhaustiveness_witnesses.is_empty()
-}
-
 /// Report unreachable arms, if any.
 fn report_arm_reachability<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     report: &UsefulnessReport<'p, 'tcx>,
 ) {
+    let report_unreachable_pattern = |span, hir_id, catchall: Option<Span>| {
+        cx.tcx.emit_spanned_lint(
+            UNREACHABLE_PATTERNS,
+            hir_id,
+            span,
+            UnreachablePattern {
+                span: if catchall.is_some() { Some(span) } else { None },
+                catchall,
+            },
+        );
+    };
+
     use Reachability::*;
     let mut catchall = None;
     for (arm, is_useful) in report.arm_usefulness.iter() {
         match is_useful {
-            Unreachable => unreachable_pattern(cx.tcx, arm.pat.span(), arm.hir_id, catchall),
+            Unreachable => report_unreachable_pattern(arm.pat.span(), arm.hir_id, catchall),
             Reachable(unreachables) if unreachables.is_empty() => {}
             // The arm is reachable, but contains unreachable subpatterns (from or-patterns).
             Reachable(unreachables) => {
@@ -692,7 +756,7 @@ fn report_arm_reachability<'p, 'tcx>(
                 // Emit lints in the order in which they occur in the file.
                 unreachables.sort_unstable();
                 for span in unreachables {
-                    unreachable_pattern(cx.tcx, span, arm.hir_id, None);
+                    report_unreachable_pattern(span, arm.hir_id, None);
                 }
             }
         }
@@ -702,26 +766,18 @@ fn report_arm_reachability<'p, 'tcx>(
     }
 }
 
-fn collect_non_exhaustive_tys<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    pat: &WitnessPat<'tcx>,
-    non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
-) {
-    if matches!(pat.ctor(), Constructor::NonExhaustive) {
-        non_exhaustive_tys.insert(pat.ty());
-    }
-    if let Constructor::IntRange(range) = pat.ctor() {
-        if range.is_beyond_boundaries(pat.ty(), tcx) {
-            // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
-            non_exhaustive_tys.insert(pat.ty());
-        }
+/// Checks for common cases of "catchall" patterns that may not be intended as such.
+fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
+    use Constructor::*;
+    match pat.ctor() {
+        Wildcard => true,
+        Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)),
+        _ => false,
     }
-    pat.iter_fields()
-        .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys))
 }
 
 /// Report that a match is not exhaustive.
-fn non_exhaustive_match<'p, 'tcx>(
+fn report_non_exhaustive_match<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     thir: &Thir<'tcx>,
     scrut_ty: Ty<'tcx>,
@@ -755,7 +811,14 @@ fn non_exhaustive_match<'p, 'tcx>(
             sp,
             format!("non-exhaustive patterns: {joined_patterns} not covered"),
         );
-        err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+        err.span_label(
+            sp,
+            format!(
+                "pattern{} {} not covered",
+                rustc_errors::pluralize!(witnesses.len()),
+                joined_patterns
+            ),
+        );
         patterns_len = witnesses.len();
         pattern = if witnesses.len() < 4 {
             witnesses
@@ -768,7 +831,17 @@ fn non_exhaustive_match<'p, 'tcx>(
         };
     };
 
-    adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
+    // Point at the definition of non-covered `enum` variants.
+    if let Some(AdtDefinedHere { adt_def_span, ty, variants }) =
+        report_adt_defined_here(cx.tcx, scrut_ty, &witnesses, true)
+    {
+        let mut multi_span = MultiSpan::from_span(adt_def_span);
+        multi_span.push_span_label(adt_def_span, "");
+        for Variant { span } in variants {
+            multi_span.push_span_label(span, "not covered");
+        }
+        err.span_note(multi_span, format!("`{ty}` defined here"));
+    }
     err.note(format!("the matched value is of type `{}`", scrut_ty));
 
     if !is_empty_match {
@@ -910,7 +983,7 @@ fn non_exhaustive_match<'p, 'tcx>(
     err.emit()
 }
 
-pub(crate) fn joined_uncovered_patterns<'p, 'tcx>(
+fn joined_uncovered_patterns<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     witnesses: &[WitnessPat<'tcx>],
 ) -> String {
@@ -931,48 +1004,51 @@ pub(crate) fn joined_uncovered_patterns<'p, 'tcx>(
     }
 }
 
-pub(crate) fn pattern_not_covered_label(
-    witnesses: &[WitnessPat<'_>],
-    joined_patterns: &str,
-) -> String {
-    format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns)
+fn collect_non_exhaustive_tys<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    pat: &WitnessPat<'tcx>,
+    non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
+) {
+    if matches!(pat.ctor(), Constructor::NonExhaustive) {
+        non_exhaustive_tys.insert(pat.ty());
+    }
+    if let Constructor::IntRange(range) = pat.ctor() {
+        if range.is_beyond_boundaries(pat.ty(), tcx) {
+            // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
+            non_exhaustive_tys.insert(pat.ty());
+        }
+    }
+    pat.iter_fields()
+        .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys))
 }
 
-/// Point at the definition of non-covered `enum` variants.
-fn adt_defined_here<'p, 'tcx>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
-    err: &mut Diagnostic,
+fn report_adt_defined_here<'tcx>(
+    tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
     witnesses: &[WitnessPat<'tcx>],
-) {
+    point_at_non_local_ty: bool,
+) -> Option<AdtDefinedHere<'tcx>> {
     let ty = ty.peel_refs();
-    if let ty::Adt(def, _) = ty.kind() {
-        let mut spans = vec![];
-        if witnesses.len() < 5 {
-            for sp in maybe_point_at_variant(cx, *def, witnesses.iter()) {
-                spans.push(sp);
-            }
-        }
-        let def_span = cx
-            .tcx
-            .hir()
-            .get_if_local(def.did())
-            .and_then(|node| node.ident())
-            .map(|ident| ident.span)
-            .unwrap_or_else(|| cx.tcx.def_span(def.did()));
-        let mut span: MultiSpan =
-            if spans.is_empty() { def_span.into() } else { spans.clone().into() };
-
-        span.push_span_label(def_span, "");
-        for pat in spans {
-            span.push_span_label(pat, "not covered");
-        }
-        err.span_note(span, format!("`{ty}` defined here"));
+    let ty::Adt(def, _) = ty.kind() else {
+        return None;
+    };
+    let adt_def_span =
+        tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
+    let adt_def_span = if point_at_non_local_ty {
+        adt_def_span.unwrap_or_else(|| tcx.def_span(def.did()))
+    } else {
+        adt_def_span?
+    };
+
+    let mut variants = vec![];
+    for span in maybe_point_at_variant(tcx, *def, witnesses.iter().take(5)) {
+        variants.push(Variant { span });
     }
+    Some(AdtDefinedHere { adt_def_span, ty, variants })
 }
 
-fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
+fn maybe_point_at_variant<'a, 'tcx: 'a>(
+    tcx: TyCtxt<'tcx>,
     def: AdtDef<'tcx>,
     patterns: impl Iterator<Item = &'a WitnessPat<'tcx>>,
 ) -> Vec<Span> {
@@ -985,7 +1061,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
             {
                 continue;
             }
-            let sp = def.variant(*variant_index).ident(cx.tcx).span;
+            let sp = def.variant(*variant_index).ident(tcx).span;
             if covered.contains(&sp) {
                 // Don't point at variants that have already been covered due to other patterns to avoid
                 // visual clutter.
@@ -993,112 +1069,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
             }
             covered.push(sp);
         }
-        covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields()));
+        covered.extend(maybe_point_at_variant(tcx, def, pattern.iter_fields()));
     }
     covered
 }
-
-/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
-/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
-///
-/// For example, this would reject:
-/// - `ref x @ Some(ref mut y)`,
-/// - `ref mut x @ Some(ref y)`,
-/// - `ref mut x @ Some(ref mut y)`,
-/// - `ref mut? x @ Some(y)`, and
-/// - `x @ Some(ref mut? y)`.
-///
-/// This analysis is *not* subsumed by NLL.
-fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) {
-    // Extract `sub` in `binding @ sub`.
-    let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else {
-        return;
-    };
-
-    let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
-
-    let sess = cx.tcx.sess;
-
-    // Get the binding move, extract the mutability if by-ref.
-    let mut_outer = match mode {
-        BindingMode::ByValue if is_binding_by_move(ty) => {
-            // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
-            let mut conflicts_ref = Vec::new();
-            sub.each_binding(|_, mode, _, span| match mode {
-                BindingMode::ByValue => {}
-                BindingMode::ByRef(_) => conflicts_ref.push(span),
-            });
-            if !conflicts_ref.is_empty() {
-                sess.emit_err(BorrowOfMovedValue {
-                    binding_span: pat.span,
-                    conflicts_ref,
-                    name,
-                    ty,
-                    suggest_borrowing: Some(pat.span.shrink_to_lo()),
-                });
-            }
-            return;
-        }
-        BindingMode::ByValue => return,
-        BindingMode::ByRef(m) => m.mutability(),
-    };
-
-    // We now have `ref $mut_outer binding @ sub` (semantically).
-    // Recurse into each binding in `sub` and find mutability or move conflicts.
-    let mut conflicts_move = Vec::new();
-    let mut conflicts_mut_mut = Vec::new();
-    let mut conflicts_mut_ref = Vec::new();
-    sub.each_binding(|name, mode, ty, span| {
-        match mode {
-            BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) {
-                // Both sides are `ref`.
-                (Mutability::Not, Mutability::Not) => {}
-                // 2x `ref mut`.
-                (Mutability::Mut, Mutability::Mut) => {
-                    conflicts_mut_mut.push(Conflict::Mut { span, name })
-                }
-                (Mutability::Not, Mutability::Mut) => {
-                    conflicts_mut_ref.push(Conflict::Mut { span, name })
-                }
-                (Mutability::Mut, Mutability::Not) => {
-                    conflicts_mut_ref.push(Conflict::Ref { span, name })
-                }
-            },
-            BindingMode::ByValue if is_binding_by_move(ty) => {
-                conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
-            }
-            BindingMode::ByValue => {} // `ref mut?` + by-copy is fine.
-        }
-    });
-
-    let report_mut_mut = !conflicts_mut_mut.is_empty();
-    let report_mut_ref = !conflicts_mut_ref.is_empty();
-    let report_move_conflict = !conflicts_move.is_empty();
-
-    let mut occurrences = match mut_outer {
-        Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }],
-        Mutability::Not => vec![Conflict::Ref { span: pat.span, name }],
-    };
-    occurrences.extend(conflicts_mut_mut);
-    occurrences.extend(conflicts_mut_ref);
-    occurrences.extend(conflicts_move);
-
-    // Report errors if any.
-    if report_mut_mut {
-        // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
-        sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences });
-    } else if report_mut_ref {
-        // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
-        match mut_outer {
-            Mutability::Mut => {
-                sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences });
-            }
-            Mutability::Not => {
-                sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences });
-            }
-        };
-    } else if report_move_conflict {
-        // Report by-ref and by-move conflicts, e.g. `ref x @ y`.
-        sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences });
-    }
-}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 1eb1dd72a61..da7b6587a72 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -311,7 +311,10 @@ use super::deconstruct_pat::{
     Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet,
     WitnessPat,
 };
-use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered};
+use crate::errors::{
+    NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap,
+    OverlappingRangeEndpoints, Uncovered,
+};
 
 use rustc_data_structures::captures::Captures;
 
@@ -337,6 +340,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
     pub(crate) module: DefId,
     pub(crate) param_env: ty::ParamEnv<'tcx>,
     pub(crate) pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
+    /// The span of the whole match, if applicable.
+    pub(crate) match_span: Option<Span>,
     /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns.
     pub(crate) refutable: bool,
 }
@@ -1149,28 +1154,50 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
 
     // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
-    if cx.refutable
-        && non_exhaustiveness_witnesses.is_empty()
-        && !matches!(
+    if cx.refutable && non_exhaustiveness_witnesses.is_empty() {
+        if !matches!(
             cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0,
             rustc_session::lint::Level::Allow
-        )
-    {
-        let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
-        if !witnesses.is_empty() {
-            // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
-            // is not exhaustive enough.
-            //
-            // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
-            cx.tcx.emit_spanned_lint(
-                NON_EXHAUSTIVE_OMITTED_PATTERNS,
-                lint_root,
-                scrut_span,
-                NonExhaustiveOmittedPattern {
-                    scrut_ty,
-                    uncovered: Uncovered::new(scrut_span, cx, witnesses),
-                },
-            );
+        ) {
+            let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
+
+            if !witnesses.is_empty() {
+                // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+                // is not exhaustive enough.
+                //
+                // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
+                cx.tcx.emit_spanned_lint(
+                    NON_EXHAUSTIVE_OMITTED_PATTERNS,
+                    lint_root,
+                    scrut_span,
+                    NonExhaustiveOmittedPattern {
+                        scrut_ty,
+                        uncovered: Uncovered::new(scrut_span, cx, witnesses),
+                    },
+                );
+            }
+        } else {
+            // We used to allow putting the `#[allow(non_exhaustive_omitted_patterns)]` on a match
+            // arm. This no longer makes sense so we warn users, to avoid silently breaking their
+            // usage of the lint.
+            for arm in arms {
+                let (lint_level, lint_level_source) =
+                    cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id);
+                if !matches!(lint_level, rustc_session::lint::Level::Allow) {
+                    let decorator = NonExhaustiveOmittedPatternLintOnArm {
+                        lint_span: lint_level_source.span(),
+                        suggest_lint_on_match: cx.match_span.map(|span| span.shrink_to_lo()),
+                        lint_level: lint_level.as_str(),
+                        lint_name: "non_exhaustive_omitted_patterns",
+                    };
+
+                    use rustc_errors::DecorateLint;
+                    let mut err = cx.tcx.sess.struct_span_warn(arm.pat.span(), "");
+                    err.set_primary_message(decorator.msg());
+                    decorator.decorate_lint(&mut err);
+                    err.emit();
+                }
+            }
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 28765af20ad..42b2f18869c 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,13 +1,12 @@
 use crate::MirPass;
-use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::IndexVec;
 use rustc_middle::mir::*;
 use rustc_middle::mir::{
     interpret::Scalar,
-    visit::{PlaceContext, Visitor},
+    visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor},
 };
-use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeAndMut};
 use rustc_session::Session;
 
 pub struct CheckAlignment;
@@ -30,7 +29,12 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment {
 
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &mut body.local_decls;
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
 
+        // This pass inserts new blocks. Each insertion changes the Location for all
+        // statements/blocks after. Iterating or visiting the MIR in order would require updating
+        // our current location after every insertion. By iterating backwards, we dodge this issue:
+        // The only Locations that an insertion changes have already been handled.
         for block in (0..basic_blocks.len()).rev() {
             let block = block.into();
             for statement_index in (0..basic_blocks[block].statements.len()).rev() {
@@ -38,22 +42,19 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment {
                 let statement = &basic_blocks[block].statements[statement_index];
                 let source_info = statement.source_info;
 
-                let mut finder = PointerFinder {
-                    local_decls,
-                    tcx,
-                    pointers: Vec::new(),
-                    def_id: body.source.def_id(),
-                };
-                for (pointer, pointee_ty) in finder.find_pointers(statement) {
-                    debug!("Inserting alignment check for {:?}", pointer.ty(&*local_decls, tcx).ty);
+                let mut finder =
+                    PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() };
+                finder.visit_statement(statement, location);
 
+                for (local, ty) in finder.pointers {
+                    debug!("Inserting alignment check for {:?}", ty);
                     let new_block = split_block(basic_blocks, location);
                     insert_alignment_check(
                         tcx,
                         local_decls,
                         &mut basic_blocks[block],
-                        pointer,
-                        pointee_ty,
+                        local,
+                        ty,
                         source_info,
                         new_block,
                     );
@@ -63,69 +64,71 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment {
     }
 }
 
-impl<'tcx, 'a> PointerFinder<'tcx, 'a> {
-    fn find_pointers(&mut self, statement: &Statement<'tcx>) -> Vec<(Place<'tcx>, Ty<'tcx>)> {
-        self.pointers.clear();
-        self.visit_statement(statement, Location::START);
-        core::mem::take(&mut self.pointers)
-    }
-}
-
 struct PointerFinder<'tcx, 'a> {
-    local_decls: &'a mut LocalDecls<'tcx>,
     tcx: TyCtxt<'tcx>,
-    def_id: DefId,
+    local_decls: &'a mut LocalDecls<'tcx>,
+    param_env: ParamEnv<'tcx>,
     pointers: Vec<(Place<'tcx>, Ty<'tcx>)>,
 }
 
 impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        if let Rvalue::AddressOf(..) = rvalue {
-            // Ignore dereferences inside of an AddressOf
-            return;
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        // We want to only check reads and writes to Places, so we specifically exclude
+        // Borrows and AddressOf.
+        match context {
+            PlaceContext::MutatingUse(
+                MutatingUseContext::Store
+                | MutatingUseContext::AsmOutput
+                | MutatingUseContext::Call
+                | MutatingUseContext::Yield
+                | MutatingUseContext::Drop,
+            ) => {}
+            PlaceContext::NonMutatingUse(
+                NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
+            ) => {}
+            _ => {
+                return;
+            }
         }
-        self.super_rvalue(rvalue, location);
-    }
 
-    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
-        if let PlaceContext::NonUse(_) = context {
-            return;
-        }
         if !place.is_indirect() {
             return;
         }
 
+        // Since Deref projections must come first and only once, the pointer for an indirect place
+        // is the Local that the Place is based on.
         let pointer = Place::from(place.local);
-        let pointer_ty = pointer.ty(&*self.local_decls, self.tcx).ty;
+        let pointer_ty = self.local_decls[place.local].ty;
 
-        // We only want to check unsafe pointers
+        // We only want to check places based on unsafe pointers
         if !pointer_ty.is_unsafe_ptr() {
-            trace!("Indirect, but not an unsafe ptr, not checking {:?}", pointer_ty);
+            trace!("Indirect, but not based on an unsafe ptr, not checking {:?}", place);
             return;
         }
 
-        let Some(pointee) = pointer_ty.builtin_deref(true) else {
-            debug!("Indirect but no builtin deref: {:?}", pointer_ty);
+        let pointee_ty =
+            pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty;
+        // Ideally we'd support this in the future, but for now we are limited to sized types.
+        if !pointee_ty.is_sized(self.tcx, self.param_env) {
+            debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
             return;
-        };
-        let mut pointee_ty = pointee.ty;
-        if pointee_ty.is_array() || pointee_ty.is_slice() || pointee_ty.is_str() {
-            pointee_ty = pointee_ty.sequence_element_type(self.tcx);
         }
 
-        if !pointee_ty.is_sized(self.tcx, self.tcx.param_env_reveal_all_normalized(self.def_id)) {
-            debug!("Unsafe pointer, but unsized: {:?}", pointer_ty);
+        // Try to detect types we are sure have an alignment of 1 and skip the check
+        // We don't need to look for str and slices, we already rejected unsized types above
+        let element_ty = match pointee_ty.kind() {
+            ty::Array(ty, _) => *ty,
+            _ => pointee_ty,
+        };
+        if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8].contains(&element_ty) {
+            debug!("Trivially aligned place type: {:?}", pointee_ty);
             return;
         }
 
-        if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8, self.tcx.types.str_]
-            .contains(&pointee_ty)
-        {
-            debug!("Trivially aligned pointee type: {:?}", pointer_ty);
-            return;
-        }
+        // Ensure that this place is based on an aligned pointer.
+        self.pointers.push((pointer, pointee_ty));
 
-        self.pointers.push((pointer, pointee_ty))
+        self.super_place(place, context, location);
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 4d0e261ed1f..261d9dd448d 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -7,6 +7,7 @@ use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::InliningThreshold;
 use rustc_session::config::OptLevel;
 
 pub fn provide(providers: &mut Providers) {
@@ -54,6 +55,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         return false;
     }
 
+    let threshold = match tcx.sess.opts.unstable_opts.cross_crate_inline_threshold {
+        InliningThreshold::Always => return true,
+        InliningThreshold::Sometimes(threshold) => threshold,
+        InliningThreshold::Never => return false,
+    };
+
     let mir = tcx.optimized_mir(def_id);
     let mut checker =
         CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 };
@@ -61,8 +68,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     checker.calls == 0
         && checker.resumes == 0
         && checker.landing_pads == 0
-        && checker.statements
-            <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100)
+        && checker.statements <= threshold
 }
 
 struct CostChecker<'b, 'tcx> {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 427cc1e1924..7de4ca66794 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -7,7 +7,7 @@ use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
-use rustc_target::abi::{FieldIdx, ReprFlags, FIRST_VARIANT};
+use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 
 pub struct ScalarReplacementOfAggregates;
 
@@ -66,7 +66,7 @@ fn escaping_locals<'tcx>(
             return true;
         }
         if let ty::Adt(def, _args) = ty.kind() {
-            if def.repr().flags.contains(ReprFlags::IS_SIMD) {
+            if def.repr().simd() {
                 // Exclude #[repr(simd)] types so that they are not de-optimized into an array
                 return true;
             }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index e51b672205c..266190da035 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -270,6 +270,9 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
         *[false] a
     } `for` parameter list
 
+parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses
+    .add_paren = add the missing parentheses
+
 parse_forgot_paren = perhaps you forgot parentheses?
 
 parse_found_expr_would_be_stmt = expected expression, found `{$token}`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 20b4292701e..8ab1ec298a1 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1378,6 +1378,34 @@ pub(crate) struct FnPtrWithGenericsSugg {
     pub for_param_list_exists: bool,
 }
 
+pub(crate) struct FnTraitMissingParen {
+    pub span: Span,
+    pub machine_applicable: bool,
+}
+
+impl AddToDiagnostic for FnTraitMissingParen {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
+        let applicability = if self.machine_applicable {
+            Applicability::MachineApplicable
+        } else {
+            Applicability::MaybeIncorrect
+        };
+        diag.span_suggestion_short(
+            self.span.shrink_to_hi(),
+            crate::fluent_generated::parse_add_paren,
+            "()",
+            applicability,
+        );
+    }
+}
+
 #[derive(Diagnostic)]
 #[diag(parse_unexpected_if_with_if)]
 pub(crate) struct UnexpectedIfWithIf(
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 36125e138b2..19690a6964b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2303,13 +2303,14 @@ impl<'a> Parser<'a> {
     /// Parses an optional `move` prefix to a closure-like construct.
     fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
         if self.eat_keyword(kw::Move) {
+            let move_kw_span = self.prev_token.span;
             // Check for `move async` and recover
             if self.check_keyword(kw::Async) {
                 let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
                 Err(errors::AsyncMoveOrderIncorrect { span: move_async_span }
                     .into_diagnostic(&self.sess.span_diagnostic))
             } else {
-                Ok(CaptureBy::Value)
+                Ok(CaptureBy::Value { move_kw: move_kw_span })
             }
         } else {
             Ok(CaptureBy::Ref)
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 253dd2a3b34..65d41ea19fd 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2278,6 +2278,18 @@ impl<'a> Parser<'a> {
                     err.span_label(ident.span, "while parsing this `fn`");
                     err.emit();
                 } else {
+                    // check for typo'd Fn* trait bounds such as
+                    // fn foo<F>() where F: FnOnce -> () {}
+                    if self.token.kind == token::RArrow {
+                        let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn]
+                            .into_iter()
+                            .any(|s| self.prev_token.is_ident_named(s));
+
+                        err.subdiagnostic(errors::FnTraitMissingParen {
+                            span: self.prev_token.span,
+                            machine_applicable,
+                        });
+                    }
                     return Err(err);
                 }
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index edcc22d56c6..93db6cfc463 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1545,7 +1545,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
             && let Some(span) = suggestion.span
-            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix("_")
+            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
             && snippet == candidate
         {
             // When the suggested binding change would be from `x` to `_x`, suggest changing the
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index f792b8f2cdd..e1eb58fecc7 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -226,7 +226,7 @@ impl CodeStats {
         }
     }
 
-    pub fn print_vtable_sizes(&self, crate_name: &str) {
+    pub fn print_vtable_sizes(&self, crate_name: Symbol) {
         let mut infos =
             std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>();
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c94e0d0ed39..f745bc390ca 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2477,7 +2477,7 @@ pub fn parse_externs(
             let mut error = handler.early_struct_error(format!(
                 "crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
             ));
-            let adjusted_name = name.replace("-", "_");
+            let adjusted_name = name.replace('-', "_");
             if crate::utils::is_ascii_ident(&adjusted_name) {
                 error.help(format!(
                     "consider replacing the dashes with underscores: `{adjusted_name}`"
@@ -3161,10 +3161,10 @@ impl PpMode {
 pub(crate) mod dep_tracking {
     use super::{
         BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression,
-        ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
-        LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
-        RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
-        SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
+        ErrorOutputType, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
+        LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
+        Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
+        SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
     };
     use crate::lint;
     use crate::options::WasiExecModel;
@@ -3270,6 +3270,7 @@ pub(crate) mod dep_tracking {
         LanguageIdentifier,
         TraitSolver,
         Polonius,
+        InliningThreshold,
     );
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
@@ -3435,3 +3436,16 @@ impl Polonius {
         matches!(self, Polonius::Next)
     }
 }
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum InliningThreshold {
+    Always,
+    Sometimes(usize),
+    Never,
+}
+
+impl Default for InliningThreshold {
+    fn default() -> Self {
+        Self::Sometimes(100)
+    }
+}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7510a41485a..964a26e94fe 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -428,6 +428,8 @@ mod desc {
         "one of supported execution strategies (`same-thread`, or `cross-thread`)";
     pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
     pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
+    pub const parse_inlining_threshold: &str =
+        "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
 }
 
 mod parse {
@@ -1310,6 +1312,26 @@ mod parse {
         };
         true
     }
+
+    pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool {
+        match v {
+            Some("always" | "yes") => {
+                *slot = InliningThreshold::Always;
+            }
+            Some("never") => {
+                *slot = InliningThreshold::Never;
+            }
+            Some(v) => {
+                if let Ok(threshold) = v.parse() {
+                    *slot = InliningThreshold::Sometimes(threshold);
+                } else {
+                    return false;
+                }
+            }
+            None => return false,
+        }
+        true
+    }
 }
 
 options! {
@@ -1479,7 +1501,7 @@ options! {
         "combine CGUs into a single one"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
         "inject the given attribute in the crate"),
-    cross_crate_inline_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
+    cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
         "threshold to allow cross crate inlining of functions"),
     debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
         "emit discriminators and other data necessary for AutoFDO"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ff470ce1fa0..f287862cc23 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -194,6 +194,9 @@ symbols! {
         Error,
         File,
         FileType,
+        Fn,
+        FnMut,
+        FnOnce,
         FormatSpec,
         Formatter,
         From,
@@ -1114,6 +1117,7 @@ symbols! {
         off,
         offset,
         offset_of,
+        offset_of_enum,
         omit_gdb_pretty_printer_section,
         on,
         on_unimplemented,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 31da437f2e9..6b09bc89873 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -28,6 +28,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
@@ -2768,20 +2769,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ));
                 }
             }
-            ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
+            ObligationCauseCode::RepeatElementCopy { is_constable, elt_type, elt_span, elt_stmt_span } => {
                 err.note(
                     "the `Copy` trait is required because this value will be copied for each element of the array",
                 );
-
-                if is_const_fn {
-                    err.help(
-                        "consider creating a new `const` item and initializing it with the result \
-                        of the function call to be used in the repeat position, like \
-                        `const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
-                    );
+                let value_kind = match is_constable {
+                    IsConstable::Fn => Some("the result of the function call"),
+                    IsConstable::Ctor => Some("the result of the constructor"),
+                    _ => None
+                };
+                let sm = tcx.sess.source_map();
+                if let Some(value_kind) = value_kind &&
+                    let Ok(snip) = sm.span_to_snippet(elt_span)
+                {
+                    let help_msg = format!(
+                        "consider creating a new `const` item and initializing it with {value_kind} \
+                        to be used in the repeat position");
+                    let indentation = sm.indentation_before(elt_stmt_span).unwrap_or_default();
+                    err.multipart_suggestion(help_msg, vec![
+                        (elt_stmt_span.shrink_to_lo(), format!("const ARRAY_REPEAT_VALUE: {elt_type} = {snip};\n{indentation}")),
+                        (elt_span, "ARRAY_REPEAT_VALUE".to_string())
+                    ], Applicability::MachineApplicable);
                 }
 
-                if self.tcx.sess.is_nightly_build() && is_const_fn {
+                if self.tcx.sess.is_nightly_build() && matches!(is_constable, IsConstable::Fn|IsConstable::Ctor) {
                     err.help(
                         "create an inline `const` block, see RFC #2920 \
                          <https://github.com/rust-lang/rfcs/pull/2920> for more information",
@@ -2938,7 +2949,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 else {
                     bug!("expected closure in SizedClosureCapture obligation");
                 };
-                if let hir::CaptureBy::Value = closure.capture_clause
+                if let hir::CaptureBy::Value { .. } = closure.capture_clause
                     && let Some(span) = closure.fn_arg_span
                 {
                     err.span_label(span, "this closure captures all values by move");
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index e4f7592c409..471d10dbdbd 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -783,7 +783,7 @@ pub struct BoundVarReplacer<'me, 'tcx> {
     // the `var` (but we *could* bring that into scope if we were to track them as we pass them).
     mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
     mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
-    mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+    mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     // The current depth relative to *this* folding, *not* the entire normalization. In other words,
     // the depth of binders we've passed here.
     current_index: ty::DebruijnIndex,
@@ -843,11 +843,11 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
         T,
         BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
         BTreeMap<ty::PlaceholderType, ty::BoundTy>,
-        BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+        BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     ) {
         let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new();
         let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new();
-        let mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar> = BTreeMap::new();
+        let mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar> = BTreeMap::new();
 
         let mut replacer = BoundVarReplacer {
             infcx,
@@ -966,7 +966,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
     infcx: &'me InferCtxt<'tcx>,
     mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
     mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
-    mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+    mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     universe_indices: &'me [Option<ty::UniverseIndex>],
     current_index: ty::DebruijnIndex,
 }
@@ -976,7 +976,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
         infcx: &'me InferCtxt<'tcx>,
         mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
         mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
-        mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
+        mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
         universe_indices: &'me [Option<ty::UniverseIndex>],
         value: T,
     ) -> T {
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 5c67188dd24..f4b6d3bcfda 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -628,15 +628,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         self.infcx.probe(|_snapshot| {
-            if obligation.has_non_region_late_bound() {
-                return;
-            }
+            let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
+            let placeholder_trait_predicate =
+                self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
 
-            // The code below doesn't care about regions, and the
-            // self-ty here doesn't escape this probe, so just erase
-            // any LBR.
-            let self_ty = self.tcx().erase_late_bound_regions(obligation.self_ty());
-            let poly_trait_ref = match self_ty.kind() {
+            let self_ty = placeholder_trait_predicate.self_ty();
+            let principal_trait_ref = match self_ty.kind() {
                 ty::Dynamic(ref data, ..) => {
                     if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
                         debug!(
@@ -668,18 +665,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 _ => return,
             };
 
-            debug!(?poly_trait_ref, "assemble_candidates_from_object_ty");
-
-            let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
-            let placeholder_trait_predicate =
-                self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
+            debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
 
             // Count only those upcast versions that match the trait-ref
             // we are looking for. Specifically, do not only check for the
             // correct trait, but also the correct type parameters.
             // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
             // but `Foo` is declared as `trait Foo: Bar<u32>`.
-            let candidate_supertraits = util::supertraits(self.tcx(), poly_trait_ref)
+            let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
                 .enumerate()
                 .filter(|&(_, upcast_trait_ref)| {
                     self.infcx.probe(|_| {
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index c8e730b585a..ace9eade7f6 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -3,18 +3,17 @@ use std::hash::Hash;
 use std::ops::ControlFlow;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_serialize::{Decodable, Encodable};
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::TyDecoder;
-use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex};
+use crate::{HashStableContext, Interner, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
+#[derive(TyEncodable, TyDecodable)]
 pub struct Canonical<I: Interner, V> {
     pub value: V,
     pub max_universe: UniverseIndex,
@@ -127,27 +126,3 @@ where
         self.variables.visit_with(folder)
     }
 }
-
-impl<I: Interner, E: TyEncoder<I = I>, V: Encodable<E>> Encodable<E> for Canonical<I, V>
-where
-    I::CanonicalVars: Encodable<E>,
-{
-    fn encode(&self, s: &mut E) {
-        self.value.encode(s);
-        self.max_universe.encode(s);
-        self.variables.encode(s);
-    }
-}
-
-impl<I: Interner, D: TyDecoder<I = I>, V: Decodable<D>> Decodable<D> for Canonical<I, V>
-where
-    I::CanonicalVars: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        Canonical {
-            value: Decodable::decode(d),
-            max_universe: Decodable::decode(d),
-            variables: Decodable::decode(d),
-        }
-    }
-}
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index cf67ba0b21a..33782b13ca8 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -1,12 +1,8 @@
 use rustc_data_structures::stable_hasher::HashStable;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_serialize::{Decodable, Decoder, Encodable};
 use std::fmt;
 
-use crate::{
-    DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder,
-    TyEncoder, WithInfcx,
-};
+use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
 
 use self::ConstKind::*;
 
@@ -20,6 +16,7 @@ use self::ConstKind::*;
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
+#[derive(TyEncodable, TyDecodable)]
 pub enum ConstKind<I: Interner> {
     /// A const generic parameter.
     Param(I::ParamConst),
@@ -92,67 +89,6 @@ where
     }
 }
 
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
-where
-    I::ParamConst: Decodable<D>,
-    I::InferConst: Decodable<D>,
-    I::BoundConst: Decodable<D>,
-    I::PlaceholderConst: Decodable<D>,
-    I::AliasConst: Decodable<D>,
-    I::ValueConst: Decodable<D>,
-    I::ErrorGuaranteed: Decodable<D>,
-    I::ExprConst: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => Param(Decodable::decode(d)),
-            1 => Infer(Decodable::decode(d)),
-            2 => Bound(Decodable::decode(d), Decodable::decode(d)),
-            3 => Placeholder(Decodable::decode(d)),
-            4 => Unevaluated(Decodable::decode(d)),
-            5 => Value(Decodable::decode(d)),
-            6 => Error(Decodable::decode(d)),
-            7 => Expr(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "ConstKind", 8,
-                )
-            ),
-        }
-    }
-}
-
-impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
-where
-    I::ParamConst: Encodable<E>,
-    I::InferConst: Encodable<E>,
-    I::BoundConst: Encodable<E>,
-    I::PlaceholderConst: Encodable<E>,
-    I::AliasConst: Encodable<E>,
-    I::ValueConst: Encodable<E>,
-    I::ErrorGuaranteed: Encodable<E>,
-    I::ExprConst: Encodable<E>,
-{
-    fn encode(&self, e: &mut E) {
-        let disc = const_kind_discriminant(self);
-        match self {
-            Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
-            Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
-            Bound(d, b) => e.emit_enum_variant(disc, |e| {
-                d.encode(e);
-                b.encode(e);
-            }),
-            Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
-            Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
-            Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
-            Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
-            Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
-        }
-    }
-}
-
 impl<I: Interner> PartialEq for ConstKind<I> {
     fn eq(&self, other: &Self) -> bool {
         match (self, other) {
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index d5cadd4e83a..8472a084505 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -115,5 +115,8 @@ bitflags! {
 
         /// Does this have `Coroutine` or `CoroutineWitness`?
         const HAS_TY_COROUTINE            = 1 << 23;
+
+        /// Does this have any binders with bound vars (e.g. that need to be anonymized)?
+        const HAS_BINDER_VARS             = 1 << 24;
     }
 }
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index a056fbeda98..e8785fff2ef 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -10,6 +10,8 @@
 #![deny(rustc::diagnostic_outside_of_impl)]
 #![allow(internal_features)]
 
+extern crate self as rustc_type_ir;
+
 #[macro_use]
 extern crate bitflags;
 #[macro_use]
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 23117fdd531..48662d42642 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,18 +1,16 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_serialize::Decoder;
-use rustc_serialize::{Decodable, Encodable};
 use std::fmt;
 use std::ops::ControlFlow;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
 use crate::{HashStableContext, Interner};
-use crate::{TyDecoder, TyEncoder};
 
 /// A clause is something that can appear in where bounds or be inferred
 /// by implied bounds.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Hash(bound = ""))]
+#[derive(TyEncodable, TyDecodable)]
 pub enum ClauseKind<I: Interner> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -161,65 +159,9 @@ where
     }
 }
 
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ClauseKind<I>
-where
-    I::Ty: Decodable<D>,
-    I::Const: Decodable<D>,
-    I::GenericArg: Decodable<D>,
-    I::TraitPredicate: Decodable<D>,
-    I::ProjectionPredicate: Decodable<D>,
-    I::TypeOutlivesPredicate: Decodable<D>,
-    I::RegionOutlivesPredicate: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => ClauseKind::Trait(Decodable::decode(d)),
-            1 => ClauseKind::RegionOutlives(Decodable::decode(d)),
-            2 => ClauseKind::TypeOutlives(Decodable::decode(d)),
-            3 => ClauseKind::Projection(Decodable::decode(d)),
-            4 => ClauseKind::ConstArgHasType(Decodable::decode(d), Decodable::decode(d)),
-            5 => ClauseKind::WellFormed(Decodable::decode(d)),
-            6 => ClauseKind::ConstEvaluatable(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "ClauseKind", 7,
-                )
-            ),
-        }
-    }
-}
-
-impl<I: Interner, E: TyEncoder> Encodable<E> for ClauseKind<I>
-where
-    I::Ty: Encodable<E>,
-    I::Const: Encodable<E>,
-    I::GenericArg: Encodable<E>,
-    I::TraitPredicate: Encodable<E>,
-    I::ProjectionPredicate: Encodable<E>,
-    I::TypeOutlivesPredicate: Encodable<E>,
-    I::RegionOutlivesPredicate: Encodable<E>,
-{
-    fn encode(&self, s: &mut E) {
-        let discriminant = clause_kind_discriminant(self);
-        match self {
-            ClauseKind::Trait(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-            ClauseKind::RegionOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-            ClauseKind::TypeOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-            ClauseKind::Projection(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-            ClauseKind::ConstArgHasType(c, t) => s.emit_enum_variant(discriminant, |s| {
-                c.encode(s);
-                t.encode(s);
-            }),
-            ClauseKind::WellFormed(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-            ClauseKind::ConstEvaluatable(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
-        }
-    }
-}
-
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Hash(bound = ""))]
+#[derive(TyEncodable, TyDecodable)]
 pub enum PredicateKind<I: Interner> {
     /// Prove a clause
     Clause(ClauseKind<I>),
@@ -418,83 +360,6 @@ where
     }
 }
 
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for PredicateKind<I>
-where
-    I::DefId: Decodable<D>,
-    I::Const: Decodable<D>,
-    I::GenericArgs: Decodable<D>,
-    I::Term: Decodable<D>,
-    I::CoercePredicate: Decodable<D>,
-    I::SubtypePredicate: Decodable<D>,
-    I::ClosureKind: Decodable<D>,
-    ClauseKind<I>: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => PredicateKind::Clause(Decodable::decode(d)),
-            1 => PredicateKind::ObjectSafe(Decodable::decode(d)),
-            2 => PredicateKind::ClosureKind(
-                Decodable::decode(d),
-                Decodable::decode(d),
-                Decodable::decode(d),
-            ),
-            3 => PredicateKind::Subtype(Decodable::decode(d)),
-            4 => PredicateKind::Coerce(Decodable::decode(d)),
-            5 => PredicateKind::ConstEquate(Decodable::decode(d), Decodable::decode(d)),
-            6 => PredicateKind::Ambiguous,
-            7 => PredicateKind::AliasRelate(
-                Decodable::decode(d),
-                Decodable::decode(d),
-                Decodable::decode(d),
-            ),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "PredicateKind", 8,
-                )
-            ),
-        }
-    }
-}
-
-impl<I: Interner, E: TyEncoder> Encodable<E> for PredicateKind<I>
-where
-    I::DefId: Encodable<E>,
-    I::Const: Encodable<E>,
-    I::GenericArgs: Encodable<E>,
-    I::Term: Encodable<E>,
-    I::CoercePredicate: Encodable<E>,
-    I::SubtypePredicate: Encodable<E>,
-    I::ClosureKind: Encodable<E>,
-    ClauseKind<I>: Encodable<E>,
-{
-    fn encode(&self, s: &mut E) {
-        let discriminant = predicate_kind_discriminant(self);
-        match self {
-            PredicateKind::Clause(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
-            PredicateKind::ObjectSafe(d) => s.emit_enum_variant(discriminant, |s| d.encode(s)),
-            PredicateKind::ClosureKind(d, g, k) => s.emit_enum_variant(discriminant, |s| {
-                d.encode(s);
-                g.encode(s);
-                k.encode(s);
-            }),
-            PredicateKind::Subtype(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
-            PredicateKind::Coerce(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
-            PredicateKind::ConstEquate(a, b) => s.emit_enum_variant(discriminant, |s| {
-                a.encode(s);
-                b.encode(s);
-            }),
-            PredicateKind::Ambiguous => s.emit_enum_variant(discriminant, |_s| {}),
-            PredicateKind::AliasRelate(a, b, d) => s.emit_enum_variant(discriminant, |s| {
-                a.encode(s);
-                b.encode(s);
-                d.encode(s);
-            }),
-        }
-    }
-}
-
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum AliasRelationDirection {
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 72f86fc0692..69ed5badaea 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,12 +1,8 @@
 use rustc_data_structures::stable_hasher::HashStable;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_serialize::{Decodable, Decoder, Encodable};
 use std::fmt;
 
-use crate::{
-    DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder,
-    TyEncoder, WithInfcx,
-};
+use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
 
 use self::RegionKind::*;
 
@@ -125,6 +121,7 @@ use self::RegionKind::*;
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
+#[derive(TyEncodable, TyDecodable)]
 pub enum RegionKind<I: Interner> {
     /// Region bound in a type or fn declaration which will be
     /// substituted 'early' -- that is, at the same time when type
@@ -245,72 +242,6 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Encodable`
-impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for RegionKind<I>
-where
-    I::EarlyBoundRegion: Encodable<E>,
-    I::BoundRegion: Encodable<E>,
-    I::FreeRegion: Encodable<E>,
-    I::InferRegion: Encodable<E>,
-    I::PlaceholderRegion: Encodable<E>,
-{
-    fn encode(&self, e: &mut E) {
-        let disc = regionkind_discriminant(self);
-        match self {
-            ReEarlyBound(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReLateBound(a, b) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-                b.encode(e);
-            }),
-            ReFree(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReStatic => e.emit_enum_variant(disc, |_| {}),
-            ReVar(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            RePlaceholder(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReErased => e.emit_enum_variant(disc, |_| {}),
-            ReError(_) => e.emit_enum_variant(disc, |_| {}),
-        }
-    }
-}
-
-// This is manually implemented because a derive would require `I: Decodable`
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I>
-where
-    I::EarlyBoundRegion: Decodable<D>,
-    I::BoundRegion: Decodable<D>,
-    I::FreeRegion: Decodable<D>,
-    I::InferRegion: Decodable<D>,
-    I::PlaceholderRegion: Decodable<D>,
-    I::ErrorGuaranteed: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => ReEarlyBound(Decodable::decode(d)),
-            1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)),
-            2 => ReFree(Decodable::decode(d)),
-            3 => ReStatic,
-            4 => ReVar(Decodable::decode(d)),
-            5 => RePlaceholder(Decodable::decode(d)),
-            6 => ReErased,
-            7 => ReError(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "RegionKind", 8,
-                )
-            ),
-        }
-    }
-}
-
 // This is not a derived impl because a derive would require `I: HashStable`
 impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
 where
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 2138c273341..09a9a332269 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -2,14 +2,11 @@
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
-use rustc_serialize::{Decodable, Decoder, Encodable};
 use std::fmt;
 use std::mem::discriminant;
 
 use crate::HashStableContext;
 use crate::Interner;
-use crate::TyDecoder;
-use crate::TyEncoder;
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
 
 use self::TyKind::*;
@@ -122,6 +119,7 @@ pub enum AliasKind {
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
+#[derive(TyEncodable, TyDecodable)]
 pub enum TyKind<I: Interner> {
     /// The primitive boolean type. Written as `bool`.
     Bool,
@@ -472,178 +470,6 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Encodable`
-impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for TyKind<I>
-where
-    I::ErrorGuaranteed: Encodable<E>,
-    I::AdtDef: Encodable<E>,
-    I::GenericArgs: Encodable<E>,
-    I::DefId: Encodable<E>,
-    I::Ty: Encodable<E>,
-    I::Const: Encodable<E>,
-    I::Region: Encodable<E>,
-    I::TypeAndMut: Encodable<E>,
-    I::PolyFnSig: Encodable<E>,
-    I::BoundExistentialPredicates: Encodable<E>,
-    I::Tys: Encodable<E>,
-    I::AliasTy: Encodable<E>,
-    I::ParamTy: Encodable<E>,
-    I::BoundTy: Encodable<E>,
-    I::PlaceholderTy: Encodable<E>,
-    I::InferTy: Encodable<E>,
-    I::AllocId: Encodable<E>,
-{
-    fn encode(&self, e: &mut E) {
-        let disc = tykind_discriminant(self);
-        match self {
-            Bool => e.emit_enum_variant(disc, |_| {}),
-            Char => e.emit_enum_variant(disc, |_| {}),
-            Int(i) => e.emit_enum_variant(disc, |e| {
-                i.encode(e);
-            }),
-            Uint(u) => e.emit_enum_variant(disc, |e| {
-                u.encode(e);
-            }),
-            Float(f) => e.emit_enum_variant(disc, |e| {
-                f.encode(e);
-            }),
-            Adt(adt, args) => e.emit_enum_variant(disc, |e| {
-                adt.encode(e);
-                args.encode(e);
-            }),
-            Foreign(def_id) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-            }),
-            Str => e.emit_enum_variant(disc, |_| {}),
-            Array(t, c) => e.emit_enum_variant(disc, |e| {
-                t.encode(e);
-                c.encode(e);
-            }),
-            Slice(t) => e.emit_enum_variant(disc, |e| {
-                t.encode(e);
-            }),
-            RawPtr(tam) => e.emit_enum_variant(disc, |e| {
-                tam.encode(e);
-            }),
-            Ref(r, t, m) => e.emit_enum_variant(disc, |e| {
-                r.encode(e);
-                t.encode(e);
-                m.encode(e);
-            }),
-            FnDef(def_id, args) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                args.encode(e);
-            }),
-            FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
-                polyfnsig.encode(e);
-            }),
-            Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| {
-                l.encode(e);
-                r.encode(e);
-                repr.encode(e);
-            }),
-            Closure(def_id, args) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                args.encode(e);
-            }),
-            Coroutine(def_id, args, m) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                args.encode(e);
-                m.encode(e);
-            }),
-            CoroutineWitness(def_id, args) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                args.encode(e);
-            }),
-            Never => e.emit_enum_variant(disc, |_| {}),
-            Tuple(args) => e.emit_enum_variant(disc, |e| {
-                args.encode(e);
-            }),
-            Alias(k, p) => e.emit_enum_variant(disc, |e| {
-                k.encode(e);
-                p.encode(e);
-            }),
-            Param(p) => e.emit_enum_variant(disc, |e| {
-                p.encode(e);
-            }),
-            Bound(d, b) => e.emit_enum_variant(disc, |e| {
-                d.encode(e);
-                b.encode(e);
-            }),
-            Placeholder(p) => e.emit_enum_variant(disc, |e| {
-                p.encode(e);
-            }),
-            Infer(i) => e.emit_enum_variant(disc, |e| {
-                i.encode(e);
-            }),
-            Error(d) => e.emit_enum_variant(disc, |e| {
-                d.encode(e);
-            }),
-        }
-    }
-}
-
-// This is manually implemented because a derive would require `I: Decodable`
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
-where
-    I::ErrorGuaranteed: Decodable<D>,
-    I::AdtDef: Decodable<D>,
-    I::GenericArgs: Decodable<D>,
-    I::DefId: Decodable<D>,
-    I::Ty: Decodable<D>,
-    I::Const: Decodable<D>,
-    I::Region: Decodable<D>,
-    I::TypeAndMut: Decodable<D>,
-    I::PolyFnSig: Decodable<D>,
-    I::BoundExistentialPredicates: Decodable<D>,
-    I::Tys: Decodable<D>,
-    I::AliasTy: Decodable<D>,
-    I::ParamTy: Decodable<D>,
-    I::AliasTy: Decodable<D>,
-    I::BoundTy: Decodable<D>,
-    I::PlaceholderTy: Decodable<D>,
-    I::InferTy: Decodable<D>,
-    I::AllocId: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => Bool,
-            1 => Char,
-            2 => Int(Decodable::decode(d)),
-            3 => Uint(Decodable::decode(d)),
-            4 => Float(Decodable::decode(d)),
-            5 => Adt(Decodable::decode(d), Decodable::decode(d)),
-            6 => Foreign(Decodable::decode(d)),
-            7 => Str,
-            8 => Array(Decodable::decode(d), Decodable::decode(d)),
-            9 => Slice(Decodable::decode(d)),
-            10 => RawPtr(Decodable::decode(d)),
-            11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
-            12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
-            13 => FnPtr(Decodable::decode(d)),
-            14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
-            15 => Closure(Decodable::decode(d), Decodable::decode(d)),
-            16 => Coroutine(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
-            17 => CoroutineWitness(Decodable::decode(d), Decodable::decode(d)),
-            18 => Never,
-            19 => Tuple(Decodable::decode(d)),
-            20 => Alias(Decodable::decode(d), Decodable::decode(d)),
-            21 => Param(Decodable::decode(d)),
-            22 => Bound(Decodable::decode(d), Decodable::decode(d)),
-            23 => Placeholder(Decodable::decode(d)),
-            24 => Infer(Decodable::decode(d)),
-            25 => Error(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "TyKind", 26,
-                )
-            ),
-        }
-    }
-}
-
 // This is not a derived impl because a derive would require `I: HashStable`
 #[allow(rustc::usage_of_ty_tykind)]
 impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
diff --git a/config.example.toml b/config.example.toml
index 66fa91d4bad..e5df28a49af 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -30,7 +30,7 @@
 #
 # If `change-id` does not match the version that is currently running,
 # `x.py` will prompt you to update it and check the related PR for more details.
-change-id = 116998
+change-id = 116881
 
 # =============================================================================
 # Tweaking how LLVM is compiled
@@ -42,11 +42,15 @@ change-id = 116998
 # Unless you're developing for a target where Rust CI doesn't build a compiler
 # toolchain or changing LLVM locally, you probably want to leave this enabled.
 #
-# All tier 1 targets are currently supported; set this to `"if-available"` if
-# you are not sure whether you're on a tier 1 target.
+# Set this to `"if-available"` if you are not sure whether you're on a tier 1 
+# target. All tier 1 targets are currently supported;
 #
 # We also currently only support this when building LLVM for the build triple.
 #
+# Set this to `"if-unchanged"` to only download if the llvm-project have not 
+# been modified. (If there are no changes or if built from tarball source, 
+# the logic is the same as "if-available")
+#
 # Note that many of the LLVM options are not currently supported for
 # downloading. Currently only the "assertions" option can be toggled.
 #download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false }
@@ -553,10 +557,11 @@ change-id = 116998
 # Whether to always use incremental compilation when building rustc
 #incremental = false
 
-# Build a multi-threaded rustc
-# FIXME(#75760): Some UI tests fail when this option is enabled.
-# NOTE: This option is NOT SUPPORTED. See #48685.
-#parallel-compiler = false
+# Build a multi-threaded rustc. This allows users to use parallel rustc
+# via the unstable option `-Z threads=n`.
+# Since stable/beta channels only allow using stable features,
+# `parallel-compiler = false` should be set for these channels.
+#parallel-compiler = true
 
 # The default linker that will be hard-coded into the generated
 # compiler for targets that don't specify a default linker explicitly
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 4f0a02da440..d33c4418e1b 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -115,7 +115,6 @@
 #![feature(const_eval_select)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_write)]
-#![feature(const_maybe_uninit_zeroed)]
 #![feature(const_pin)]
 #![feature(const_refs_to_cell)]
 #![feature(const_size_of_val)]
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index bd66ad61219..817b93720ce 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -305,10 +305,13 @@ impl<T, A: Allocator> RawVec<T, A> {
     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
     pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
         if self.needs_to_grow(len, additional) {
-            self.grow_amortized(len, additional)
-        } else {
-            Ok(())
+            self.grow_amortized(len, additional)?;
+        }
+        unsafe {
+            // Inform the optimizer that the reservation has succeeded or wasn't needed
+            core::intrinsics::assume(!self.needs_to_grow(len, additional));
         }
+        Ok(())
     }
 
     /// Ensures that the buffer contains at least enough space to hold `len +
@@ -339,7 +342,14 @@ impl<T, A: Allocator> RawVec<T, A> {
         len: usize,
         additional: usize,
     ) -> Result<(), TryReserveError> {
-        if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) }
+        if self.needs_to_grow(len, additional) {
+            self.grow_exact(len, additional)?;
+        }
+        unsafe {
+            // Inform the optimizer that the reservation has succeeded or wasn't needed
+            core::intrinsics::assume(!self.needs_to_grow(len, additional));
+        }
+        Ok(())
     }
 
     /// Shrinks the buffer down to the specified capacity. If the given amount
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 89125b7955e..8c01b0973d6 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -138,7 +138,7 @@ pub const fn identity<T>(x: T) -> T {
 ///
 /// [dereferenceable types]: core::ops::Deref
 /// [pointed-to value]: core::ops::Deref::Target
-/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion
+/// ['`Deref` coercion']: core::ops::Deref#deref-coercion
 ///
 /// ```
 /// let x = Box::new(5i32);
@@ -244,7 +244,7 @@ pub trait AsRef<T: ?Sized> {
 ///
 /// [mutably dereferenceable types]: core::ops::DerefMut
 /// [pointed-to value]: core::ops::Deref::Target
-/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion
+/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion
 ///
 /// ```
 /// let mut x = Box::new(5i32);
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 1170221c10c..f1a7ad93548 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -439,10 +439,10 @@ where
 /// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise
 /// prepared to generate a value requested). eg, `backtrace::Backtrace` or
 /// `std::backtrace::Backtrace`
-/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case
-/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and
-/// `request_value` are available to simplify obtaining an ``Option<T>`` for a given type. * The
-/// Producer, when requested, populates the given Request object which is given as a mutable
+/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the
+/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and
+/// `request_value` to simplify obtaining an `Option<T>` for a given type.
+/// * The Producer, when requested, populates the given Request object which is given as a mutable
 /// reference.
 /// * The Consumer extracts a value or reference to the requested type from the `Request` object
 /// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 964aa3906f1..f855b2ad483 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1072,7 +1072,7 @@ extern "rust-intrinsic" {
     /// zero-initialization: This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+    #[rustc_const_stable(feature = "const_assert_type2", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn assert_zero_valid<T>();
@@ -1080,7 +1080,7 @@ extern "rust-intrinsic" {
     /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+    #[rustc_const_stable(feature = "const_assert_type2", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn assert_mem_uninitialized_valid<T>();
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 125a6f57bfb..7f5908e477c 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1044,6 +1044,7 @@ pub(crate) mod builtin {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_builtin_macro]
     #[macro_export]
+    #[rustc_diagnostic_item = "env_macro"] // useful for external lints
     macro_rules! env {
         ($name:expr $(,)?) => {{ /* compiler built-in */ }};
         ($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }};
@@ -1074,6 +1075,7 @@ pub(crate) mod builtin {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_builtin_macro]
     #[macro_export]
+    #[rustc_diagnostic_item = "option_env_macro"] // useful for external lints
     macro_rules! option_env {
         ($name:expr $(,)?) => {{ /* compiler built-in */ }};
     }
@@ -1479,6 +1481,7 @@ pub(crate) mod builtin {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_builtin_macro]
     #[macro_export]
+    #[rustc_diagnostic_item = "include_macro"] // useful for external lints
     macro_rules! include {
         ($file:expr $(,)?) => {{ /* compiler built-in */ }};
     }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 855bb1675c5..8a4070ebd96 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -374,6 +374,9 @@ impl<T> MaybeUninit<T> {
     /// assert_eq!(x, (0, false));
     /// ```
     ///
+    /// This can be used in const contexts, such as to indicate the end of static arrays for
+    /// plugin registration.
+    ///
     /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()`
     /// when `0` is not a valid bit-pattern for the type:
     ///
@@ -387,17 +390,19 @@ impl<T> MaybeUninit<T> {
     /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
     /// // This is undefined behavior. ⚠️
     /// ```
-    #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")]
-    #[must_use]
     #[inline]
+    #[must_use]
     #[rustc_diagnostic_item = "maybe_uninit_zeroed"]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
+    // These are OK to allow since we do not leak &mut to user-visible API
+    #[rustc_allow_const_fn_unstable(const_mut_refs)]
+    #[rustc_allow_const_fn_unstable(const_ptr_write)]
+    #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)]
+    #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "CURRENT_RUSTC_VERSION")]
     pub const fn zeroed() -> MaybeUninit<T> {
         let mut u = MaybeUninit::<T>::uninit();
         // SAFETY: `u.as_mut_ptr()` points to allocated memory.
-        unsafe {
-            u.as_mut_ptr().write_bytes(0u8, 1);
-        }
+        unsafe { u.as_mut_ptr().write_bytes(0u8, 1) };
         u
     }
 
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 9159ecb740d..c964596dd5f 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -647,7 +647,8 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
 #[allow(deprecated)]
 #[rustc_diagnostic_item = "mem_zeroed"]
 #[track_caller]
-pub unsafe fn zeroed<T>() -> T {
+#[rustc_const_stable(feature = "const_mem_zeroed", since = "CURRENT_RUSTC_VERSION")]
+pub const unsafe fn zeroed<T>() -> T {
     // SAFETY: the caller must guarantee that an all-zero value is valid for `T`.
     unsafe {
         intrinsics::assert_zero_valid::<T>();
@@ -1357,6 +1358,7 @@ impl<T> SizedTypeProperties for T {}
 ///
 /// ```
 /// #![feature(offset_of)]
+/// # #![cfg_attr(not(bootstrap), feature(offset_of_enum))]
 ///
 /// use std::mem;
 /// #[repr(C)]
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index d6f2f5ca366..99adbb91599 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -3,40 +3,107 @@
 /// In addition to being used for explicit dereferencing operations with the
 /// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
 /// by the compiler in many circumstances. This mechanism is called
-/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
+/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and
+/// mutable deref coercion similarly occurs.
 ///
-/// Implementing `Deref` for smart pointers makes accessing the data behind them
-/// convenient, which is why they implement `Deref`. On the other hand, the
-/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
-/// accommodate smart pointers. Because of this, **`Deref` should only be
-/// implemented for smart pointers** to avoid confusion.
+/// **Warning:** Deref coercion is a powerful language feature which has
+/// far-reaching implications for every type that implements `Deref`. The
+/// compiler will silently insert calls to `Deref::deref`. For this reason, one
+/// should be careful about implementing `Deref` and only do so when deref
+/// coercion is desirable. See [below][implementing] for advice on when this is
+/// typically desirable or undesirable.
 ///
-/// For similar reasons, **this trait should never fail**. Failure during
-/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
+/// Types that implement `Deref` or `DerefMut` are often called "smart
+/// pointers" and the mechanism of deref coercion has been specifically designed
+/// to facilitate the pointer-like behaviour that name suggests. Often, the
+/// purpose of a "smart pointer" type is to change the ownership semantics
+/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
+/// storage semantics of a contained value (for example, [`Box`][box]).
 ///
-/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
-/// specified, but users of the trait must ensure that such logic errors do *not* result in
-/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
-/// method.
+/// # Deref coercion
 ///
-/// # More on `Deref` coercion
+/// If `T` implements `Deref<Target = U>`, and `v` is a value of type `T`, then:
 ///
-/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
-///
-/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
-///   is equivalent to `*Deref::deref(&x)`.
+/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw
+///   pointer) is equivalent to `*Deref::deref(&v)`.
 /// * Values of type `&T` are coerced to values of type `&U`
-/// * `T` implicitly implements all the (immutable) methods of the type `U`.
+/// * `T` implicitly implements all the methods of the type `U` which take the
+///   `&self` receiver.
 ///
 /// For more details, visit [the chapter in *The Rust Programming Language*][book]
 /// as well as the reference sections on [the dereference operator][ref-deref-op],
-/// [method resolution] and [type coercions].
+/// [method resolution], and [type coercions].
+///
+/// # When to implement `Deref` or `DerefMut`
+///
+/// The same advice applies to both deref traits. In general, deref traits
+/// **should** be implemented if:
+///
+/// 1. a value of the type transparently behaves like a value of the target
+///    type;
+/// 1. the implementation of the deref function is cheap; and
+/// 1. users of the type will not be surprised by any deref coercion behaviour.
+///
+/// In general, deref traits **should not** be implemented if:
+///
+/// 1. the deref implementations could fail unexpectedly; or
+/// 1. the type has methods that are likely to collide with methods on the
+///    target type; or
+/// 1. committing to deref coercion as part of the public API is not desirable.
+///
+/// Note that there's a large difference between implementing deref traits
+/// generically over many target types, and doing so only for specific target
+/// types.
+///
+/// Generic implementations, such as for [`Box<T>`][box] (which is generic over
+/// every type and dereferences to `T`) should be careful to provide few or no
+/// methods, since the target type is unknown and therefore every method could
+/// collide with one on the target type, causing confusion for users.
+/// `impl<T> Box<T>` has no methods (though several associated functions),
+/// partly for this reason.
+///
+/// Specific implementations, such as for [`String`][string] (whose `Deref`
+/// implementation has `Target = str`) can have many methods, since avoiding
+/// collision is much easier. `String` and `str` both have many methods, and
+/// `String` additionally behaves as if it has every method of `str` because of
+/// deref coercion. The implementing type may also be generic while the
+/// implementation is still specific in this sense; for example, [`Vec<T>`][vec]
+/// dereferences to `[T]`, so methods of `T` are not applicable.
+///
+/// Consider also that deref coericion means that deref traits are a much larger
+/// part of a type's public API than any other trait as it is implicitly called
+/// by the compiler. Therefore, it is advisable to consider whether this is
+/// something you are comfortable supporting as a public API.
+///
+/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar
+/// signatures to `Deref`. It may be desirable to implement either or both of
+/// these, whether in addition to or rather than deref traits. See their
+/// documentation for details.
+///
+/// # Fallibility
+///
+/// **This trait's method should never unexpectedly fail**. Deref coercion means
+/// the compiler will often insert calls to `Deref::deref` implicitly. Failure
+/// during dereferencing can be extremely confusing when `Deref` is invoked
+/// implicitly. In the majority of uses it should be infallible, though it may
+/// be acceptable to panic if the type is misused through programmer error, for
+/// example.
+///
+/// However, infallibility is not enforced and therefore not guaranteed.
+/// As such, `unsafe` code should not rely on infallibility in general for
+/// soundness.
 ///
 /// [book]: ../../book/ch15-02-deref.html
-/// [more]: #more-on-deref-coercion
+/// [coercion]: #deref-coercion
+/// [implementing]: #when-to-implement-deref-or-derefmut
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
 /// [type coercions]: ../../reference/type-coercions.html
+/// [box]: ../../alloc/boxed/struct.Box.html
+/// [string]: ../../alloc/string/struct.String.html
+/// [vec]: ../../alloc/vec/struct.Vec.html
+/// [rc]: ../../alloc/rc/struct.Rc.html
+/// [cow]: ../../alloc/borrow/enum.Cow.html
 ///
 /// # Examples
 ///
@@ -107,30 +174,29 @@ impl<T: ?Sized> Deref for &mut T {
 /// In addition to being used for explicit dereferencing operations with the
 /// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
 /// by the compiler in many circumstances. This mechanism is called
-/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
-///
-/// Implementing `DerefMut` for smart pointers makes mutating the data behind
-/// them convenient, which is why they implement `DerefMut`. On the other hand,
-/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
-/// accommodate smart pointers. Because of this, **`DerefMut` should only be
-/// implemented for smart pointers** to avoid confusion.
+/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used.
 ///
-/// For similar reasons, **this trait should never fail**. Failure during
-/// dereferencing can be extremely confusing when `DerefMut` is invoked
-/// implicitly.
+/// **Warning:** Deref coercion is a powerful language feature which has
+/// far-reaching implications for every type that implements `DerefMut`. The
+/// compiler will silently insert calls to `DerefMut::deref_mut`. For this
+/// reason, one should be careful about implementing `DerefMut` and only do so
+/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing]
+/// for advice on when this is typically desirable or undesirable.
 ///
-/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
-/// specified, but users of the trait must ensure that such logic errors do *not* result in
-/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
-/// method.
+/// Types that implement `DerefMut` or `Deref` are often called "smart
+/// pointers" and the mechanism of deref coercion has been specifically designed
+/// to facilitate the pointer-like behaviour that name suggests. Often, the
+/// purpose of a "smart pointer" type is to change the ownership semantics
+/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
+/// storage semantics of a contained value (for example, [`Box`][box]).
 ///
-/// # More on `Deref` coercion
+/// # Mutable deref coercion
 ///
-/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
+/// If `T` implements `DerefMut<Target = U>`, and `v` is a value of type `T`,
 /// then:
 ///
-/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
-///   is equivalent to `*DerefMut::deref_mut(&mut x)`.
+/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer)
+///   is equivalent to `*DerefMut::deref_mut(&mut v)`.
 /// * Values of type `&mut T` are coerced to values of type `&mut U`
 /// * `T` implicitly implements all the (mutable) methods of the type `U`.
 ///
@@ -138,11 +204,29 @@ impl<T: ?Sized> Deref for &mut T {
 /// as well as the reference sections on [the dereference operator][ref-deref-op],
 /// [method resolution] and [type coercions].
 ///
+/// # Fallibility
+///
+/// **This trait's method should never unexpectedly fail**. Deref coercion means
+/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly.
+/// Failure during dereferencing can be extremely confusing when `DerefMut` is
+/// invoked implicitly. In the majority of uses it should be infallible, though
+/// it may be acceptable to panic if the type is misused through programmer
+/// error, for example.
+///
+/// However, infallibility is not enforced and therefore not guaranteed.
+/// As such, `unsafe` code should not rely on infallibility in general for
+/// soundness.
+///
 /// [book]: ../../book/ch15-02-deref.html
-/// [more]: #more-on-deref-coercion
+/// [coercion]: #mutable-deref-coercion
+/// [implementing]: Deref#when-to-implement-deref-or-derefmut
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
 /// [type coercions]: ../../reference/type-coercions.html
+/// [box]: ../../alloc/boxed/struct.Box.html
+/// [string]: ../../alloc/string/struct.String.html
+/// [rc]: ../../alloc/rc/struct.Rc.html
+/// [cow]: ../../alloc/borrow/enum.Cow.html
 ///
 /// # Examples
 ///
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index f3695d16d7a..87e49210874 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -283,7 +283,7 @@ mod prim_never {}
 /// `char` type. For technical reasons, there is additional, separate
 /// documentation in [the `std::char` module](char/index.html) as well.
 ///
-/// # Validity
+/// # Validity and Layout
 ///
 /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]'
 /// other than a [surrogate code point]. This has a fixed numerical definition:
@@ -291,7 +291,7 @@ mod prim_never {}
 /// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF.
 ///
 /// No `char` may be constructed, whether as a literal or at runtime, that is not a
-/// Unicode scalar value:
+/// Unicode scalar value. Violating this rule causes undefined behavior.
 ///
 /// ```compile_fail
 /// // Each of these is a compiler error
@@ -308,9 +308,10 @@ mod prim_never {}
 /// let _ = unsafe { char::from_u32_unchecked(0x110000) };
 /// ```
 ///
-/// USVs are also the exact set of values that may be encoded in UTF-8. Because
-/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store
-/// any `char` in a `str` or read any character from a `str` as a `char`.
+/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because
+/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are
+/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read
+/// any character from a `str` as a `char`.
 ///
 /// The gap in valid `char` values is understood by the compiler, so in the
 /// below example the two ranges are understood to cover the whole range of
@@ -324,11 +325,17 @@ mod prim_never {}
 /// };
 /// ```
 ///
-/// All USVs are valid `char` values, but not all of them represent a real
-/// character. Many USVs are not currently assigned to a character, but may be
-/// in the future ("reserved"); some will never be a character
-/// ("noncharacters"); and some may be given different meanings by different
-/// users ("private use").
+/// All Unicode scalar values are valid `char` values, but not all of them represent a real
+/// character. Many Unicode scalar values are not currently assigned to a character, but may be in
+/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given
+/// different meanings by different users ("private use").
+///
+/// `char` is guaranteed to have the same size and alignment as `u32` on all
+/// platforms.
+/// ```
+/// use std::alloc::Layout;
+/// assert_eq!(Layout::new::<char>(), Layout::new::<u32>());
+/// ```
 ///
 /// [Unicode code point]: https://www.unicode.org/glossary/#code_point
 /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
@@ -887,8 +894,6 @@ mod prim_slice {}
 /// type. It is usually seen in its borrowed form, `&str`. It is also the type
 /// of string literals, `&'static str`.
 ///
-/// String slices are always valid UTF-8.
-///
 /// # Basic Usage
 ///
 /// String literals are string slices:
@@ -942,6 +947,14 @@ mod prim_slice {}
 /// Note: This example shows the internals of `&str`. `unsafe` should not be
 /// used to get a string slice under normal circumstances. Use `as_str`
 /// instead.
+///
+/// # Invariant
+///
+/// Rust libraries may assume that string slices are always valid UTF-8.
+///
+/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function
+/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string
+/// slice can lead to undefined behavior down the road.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_str {}
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 84b179df8c1..63e42a8784c 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -505,6 +505,10 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 
 /// Creates a null raw pointer.
 ///
+/// This function is equivalent to zero-initializing the pointer:
+/// `MaybeUninit::<*const T>::zeroed().assume_init()`.
+/// The resulting pointer has the address 0.
+///
 /// # Examples
 ///
 /// ```
@@ -512,6 +516,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 ///
 /// let p: *const i32 = ptr::null();
 /// assert!(p.is_null());
+/// assert_eq!(p as usize, 0); // this pointer has the address 0
 /// ```
 #[inline(always)]
 #[must_use]
@@ -526,6 +531,10 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
 
 /// Creates a null mutable raw pointer.
 ///
+/// This function is equivalent to zero-initializing the pointer:
+/// `MaybeUninit::<*mut T>::zeroed().assume_init()`.
+/// The resulting pointer has the address 0.
+///
 /// # Examples
 ///
 /// ```
@@ -533,6 +542,7 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
 ///
 /// let p: *mut i32 = ptr::null_mut();
 /// assert!(p.is_null());
+/// assert_eq!(p as usize, 0); // this pointer has the address 0
 /// ```
 #[inline(always)]
 #[must_use]
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index db76d26257a..993a608f42b 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -628,9 +628,14 @@ where
     let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot };
     let pivot = &*tmp;
 
+    let len = v.len();
+    if len == 0 {
+        return 0;
+    }
+
     // Now partition the slice.
     let mut l = 0;
-    let mut r = v.len();
+    let mut r = len;
     loop {
         // SAFETY: The unsafety below involves indexing an array.
         // For the first one: We already do the bounds checking here with `l < r`.
@@ -643,8 +648,11 @@ where
             }
 
             // Find the last element equal to the pivot.
-            while l < r && is_less(pivot, v.get_unchecked(r - 1)) {
+            loop {
                 r -= 1;
+                if l >= r || !is_less(pivot, v.get_unchecked(r)) {
+                    break;
+                }
             }
 
             // Are we done?
@@ -653,7 +661,6 @@ where
             }
 
             // Swap the found pair of out-of-order elements.
-            r -= 1;
             let ptr = v.as_mut_ptr();
             ptr::swap(ptr.add(l), ptr.add(r));
             l += 1;
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index b63fd5c9095..817e39942c0 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -231,6 +231,10 @@ impl fmt::Debug for Context<'_> {
 /// this might be done to wake a future when a blocking function call completes on another
 /// thread.
 ///
+/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead
+/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker
+/// unnecessarily if the two wakers [wake the same task](Self::will_wake).
+///
 /// [`Future::poll()`]: core::future::Future::poll
 /// [`Poll::Pending`]: core::task::Poll::Pending
 #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
@@ -302,7 +306,9 @@ impl Waker {
     /// when the `Waker`s would awaken the same task. However, if this function
     /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
     ///
-    /// This function is primarily used for optimization purposes.
+    /// This function is primarily used for optimization purposes — for example,
+    /// this type's [`clone_from`](Self::clone_from) implementation uses it to
+    /// avoid cloning the waker when they would wake the same task anyway.
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
@@ -382,6 +388,13 @@ impl Clone for Waker {
             waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
         }
     }
+
+    #[inline]
+    fn clone_from(&mut self, source: &Self) {
+        if !self.will_wake(source) {
+            *self = source.clone();
+        }
+    }
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 5c2e18745ea..20498b16cb2 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -565,3 +565,24 @@ fn offset_of_addr() {
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
 }
+
+#[test]
+fn const_maybe_uninit_zeroed() {
+    // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term)
+    #[repr(C)]
+    struct Foo {
+        a: Option<&'static str>,
+        b: Bar,
+        c: f32,
+        d: *const u8,
+    }
+    #[repr(C)]
+    struct Bar(usize);
+    struct FooPtr(*const Foo);
+    unsafe impl Sync for FooPtr {}
+
+    static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr());
+    const SIZE: usize = size_of::<Foo>();
+
+    assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]);
+}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 2eb7608c7ae..f666b18887c 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,8 +17,8 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-libc = { version = "0.2.149", default-features = false, features = ['rustc-dep-of-std'], public = true }
-compiler_builtins = { version = "0.1.100" }
+libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true }
+compiler_builtins = { version = "0.1.103" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs
index 57d226a3771..4d51a719f6c 100644
--- a/library/std/src/io/copy.rs
+++ b/library/std/src/io/copy.rs
@@ -1,6 +1,7 @@
 use super::{BorrowedBuf, BufReader, BufWriter, Read, Result, Write, DEFAULT_BUF_SIZE};
 use crate::alloc::Allocator;
 use crate::cmp;
+use crate::cmp::min;
 use crate::collections::VecDeque;
 use crate::io::IoSlice;
 use crate::mem::MaybeUninit;
@@ -263,36 +264,67 @@ impl<A: Allocator> BufferedWriterSpec for Vec<u8, A> {
     fn copy_from<R: Read + ?Sized>(&mut self, reader: &mut R) -> Result<u64> {
         let mut bytes = 0;
 
-        // avoid allocating before we have determined that there's anything to read
-        if self.capacity() == 0 {
-            bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?;
-            if bytes == 0 {
-                return Ok(0);
+        // avoid inflating empty/small vecs before we have determined that there's anything to read
+        if self.capacity() < DEFAULT_BUF_SIZE {
+            let stack_read_limit = DEFAULT_BUF_SIZE as u64;
+            bytes = stack_buffer_copy(&mut reader.take(stack_read_limit), self)?;
+            // fewer bytes than requested -> EOF reached
+            if bytes < stack_read_limit {
+                return Ok(bytes);
             }
         }
 
+        // don't immediately offer the vec's whole spare capacity, otherwise
+        // we might have to fully initialize it if the reader doesn't have a custom read_buf() impl
+        let mut max_read_size = DEFAULT_BUF_SIZE;
+
         loop {
             self.reserve(DEFAULT_BUF_SIZE);
-            let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into();
-            match reader.read_buf(buf.unfilled()) {
-                Ok(()) => {}
-                Err(e) if e.is_interrupted() => continue,
-                Err(e) => return Err(e),
-            };
+            let mut initialized_spare_capacity = 0;
 
-            let read = buf.filled().len();
-            if read == 0 {
-                break;
-            }
+            loop {
+                let buf = self.spare_capacity_mut();
+                let read_size = min(max_read_size, buf.len());
+                let mut buf = BorrowedBuf::from(&mut buf[..read_size]);
+                // SAFETY: init is either 0 or the init_len from the previous iteration.
+                unsafe {
+                    buf.set_init(initialized_spare_capacity);
+                }
+                match reader.read_buf(buf.unfilled()) {
+                    Ok(()) => {
+                        let bytes_read = buf.len();
 
-            // SAFETY: BorrowedBuf guarantees all of its filled bytes are init
-            // and the number of read bytes can't exceed the spare capacity since
-            // that's what the buffer is borrowing from.
-            unsafe { self.set_len(self.len() + read) };
-            bytes += read as u64;
-        }
+                        // EOF
+                        if bytes_read == 0 {
+                            return Ok(bytes);
+                        }
 
-        Ok(bytes)
+                        // the reader is returning short reads but it doesn't call ensure_init()
+                        if buf.init_len() < buf.capacity() {
+                            max_read_size = usize::MAX;
+                        }
+                        // the reader hasn't returned short reads so far
+                        if bytes_read == buf.capacity() {
+                            max_read_size *= 2;
+                        }
+
+                        initialized_spare_capacity = buf.init_len() - bytes_read;
+                        bytes += bytes_read as u64;
+                        // SAFETY: BorrowedBuf guarantees all of its filled bytes are init
+                        // and the number of read bytes can't exceed the spare capacity since
+                        // that's what the buffer is borrowing from.
+                        unsafe { self.set_len(self.len() + bytes_read) };
+
+                        // spare capacity full, reserve more
+                        if self.len() == self.capacity() {
+                            break;
+                        }
+                    }
+                    Err(e) if e.is_interrupted() => continue,
+                    Err(e) => return Err(e),
+                }
+            }
+        }
     }
 }
 
diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index 034ddd8df9a..95044de2a09 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -306,8 +306,9 @@ impl<'a> BorrowedCursor<'a> {
 
 impl<'a> Write for BorrowedCursor<'a> {
     fn write(&mut self, buf: &[u8]) -> Result<usize> {
-        self.append(buf);
-        Ok(buf.len())
+        let amt = cmp::min(buf.len(), self.capacity());
+        self.append(&buf[..amt]);
+        Ok(amt)
     }
 
     #[inline]
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml
index eab2717c452..9aa552ed81a 100644
--- a/library/unwind/Cargo.toml
+++ b/library/unwind/Cargo.toml
@@ -19,9 +19,6 @@ libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features =
 compiler_builtins = "0.1.0"
 cfg-if = "1.0"
 
-[build-dependencies]
-cc = "1.0.76"
-
 [features]
 
 # Only applies for Linux and Fuchsia targets
diff --git a/library/unwind/build.rs b/library/unwind/build.rs
deleted file mode 100644
index 5c3c02fb6ad..00000000000
--- a/library/unwind/build.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-use std::env;
-
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CARGO_CFG_MIRI");
-
-    if env::var_os("CARGO_CFG_MIRI").is_some() {
-        // Miri doesn't need the linker flags or a libunwind build.
-        return;
-    }
-
-    let target = env::var("TARGET").expect("TARGET was not set");
-    if target.contains("android") {
-        let build = cc::Build::new();
-
-        // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
-        // check if we have `libunwind` available and if so use it. Otherwise
-        // fall back to `libgcc` to support older ndk versions.
-        let has_unwind = build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
-
-        if has_unwind {
-            println!("cargo:rustc-cfg=feature=\"system-llvm-libunwind\"");
-        }
-    }
-}
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index e86408a9ed2..335bded71c1 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -76,14 +76,10 @@ cfg_if::cfg_if! {
 cfg_if::cfg_if! {
     if #[cfg(feature = "llvm-libunwind")] {
         compile_error!("`llvm-libunwind` is not supported for Android targets");
-    } else if #[cfg(feature = "system-llvm-libunwind")] {
+    } else {
         #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
         #[link(name = "unwind", cfg(not(target_feature = "crt-static")))]
         extern "C" {}
-    } else {
-        #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
-        #[link(name = "gcc", cfg(not(target_feature = "crt-static")))]
-        extern "C" {}
     }
 }
 // Android's unwinding library depends on dl_iterate_phdr in `libdl`.
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 346bfb30fec..57113b0ec62 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -181,16 +181,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "crossbeam-channel"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
 name = "crossbeam-deque"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -324,15 +314,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -444,16 +425,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
 name = "object"
 version = "0.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -514,25 +485,22 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.6.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
 dependencies = [
- "crossbeam-deque",
  "either",
  "rayon-core",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.10.1"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
 dependencies = [
- "crossbeam-channel",
  "crossbeam-deque",
  "crossbeam-utils",
- "num_cpus",
 ]
 
 [[package]]
diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml
index 113df88d7c3..7c33ce958c9 100644
--- a/src/bootstrap/defaults/config.codegen.toml
+++ b/src/bootstrap/defaults/config.codegen.toml
@@ -10,7 +10,7 @@ assertions = true
 # enable warnings during the llvm compilation
 enable-warnings = true
 # build llvm from source
-download-ci-llvm = false
+download-ci-llvm = "if-unchanged"
 
 [rust]
 # This enables `RUSTC_LOG=debug`, avoiding confusing situations
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index ffc38057900..9998fe2f5db 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/113996
+Last change is for: https://github.com/rust-lang/rust/pull/116881
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 1eed534150b..8ab0ef61c50 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -413,11 +413,6 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
 
     let mut features = String::new();
 
-    // Cranelift doesn't support `asm`.
-    if stage != 0 && builder.config.default_codegen_backend().unwrap_or_default() == "cranelift" {
-        features += " compiler-builtins-no-asm";
-    }
-
     if builder.no_std(target) == Some(true) {
         features += " compiler-builtins-mem";
         if !target.starts_with("bpf") {
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index b578c5ec295..950845b736f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1298,6 +1298,10 @@ impl Step for CodegenBackend {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
+        if builder.config.dry_run() {
+            return None;
+        }
+
         // This prevents rustc_codegen_cranelift from being built for "dist"
         // or "install" on the stable/beta channels. It is not yet stable and
         // should not be included.
@@ -1305,6 +1309,10 @@ impl Step for CodegenBackend {
             return None;
         }
 
+        if !builder.config.rust_codegen_backends.contains(&self.backend) {
+            return None;
+        }
+
         if self.backend == "cranelift" {
             if !target_supports_cranelift_backend(self.compiler.host) {
                 builder.info("target not supported by rustc_codegen_cranelift. skipping");
@@ -1343,12 +1351,15 @@ impl Step for CodegenBackend {
         let backends_dst = PathBuf::from("lib").join(&backends_rel);
 
         let backend_name = format!("rustc_codegen_{}", backend);
+        let mut found_backend = false;
         for backend in fs::read_dir(&backends_src).unwrap() {
             let file_name = backend.unwrap().file_name();
             if file_name.to_str().unwrap().contains(&backend_name) {
                 tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644);
+                found_backend = true;
             }
         }
+        assert!(found_backend);
 
         Some(tarball.generate())
     }
@@ -2208,23 +2219,19 @@ impl Step for RustDev {
         builder.ensure(crate::core::build_steps::llvm::Lld { target });
 
         let src_bindir = builder.llvm_out(target).join("bin");
-        // If updating this list, you likely want to change
+        // If updating this, you likely want to change
         // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users
         // will not pick up the extra file until LLVM gets bumped.
-        for bin in &[
-            "llvm-config",
-            "llvm-ar",
-            "llvm-objdump",
-            "llvm-profdata",
-            "llvm-bcanalyzer",
-            "llvm-cov",
-            "llvm-dwp",
-            "llvm-nm",
-            "llvm-dwarfdump",
-            "llvm-dis",
-            "llvm-tblgen",
-        ] {
-            tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
+        // We should include all the build artifacts obtained from a source build,
+        // so that you can use the downloadable LLVM as if you’ve just run a full source build.
+        if src_bindir.exists() {
+            for entry in walkdir::WalkDir::new(&src_bindir) {
+                let entry = t!(entry);
+                if entry.file_type().is_file() && !entry.path_is_symlink() {
+                    let name = entry.file_name().to_str().unwrap();
+                    tarball.add_file(src_bindir.join(name), "bin", 0o755);
+                }
+            }
         }
 
         // We don't build LLD on some platforms, so only add it if it exists
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 628a4ece8e9..e3fd942fc38 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -685,19 +685,6 @@ impl Step for Rustc {
             target,
         );
 
-        // This uses a shared directory so that librustdoc documentation gets
-        // correctly built and merged with the rustc documentation. This is
-        // needed because rustdoc is built in a different directory from
-        // rustc. rustdoc needs to be able to see everything, for example when
-        // merging the search index, or generating local (relative) links.
-        let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc");
-        t!(fs::create_dir_all(out_dir.parent().unwrap()));
-        symlink_dir_force(&builder.config, &out, &out_dir);
-        // Cargo puts proc macros in `target/doc` even if you pass `--target`
-        // explicitly (https://github.com/rust-lang/cargo/issues/7677).
-        let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc");
-        symlink_dir_force(&builder.config, &out, &proc_macro_out_dir);
-
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc");
         cargo.rustdocflag("--document-private-items");
@@ -724,6 +711,7 @@ impl Step for Rustc {
 
         let mut to_open = None;
 
+        let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc");
         for krate in &*self.crates {
             // Create all crate output directories first to make sure rustdoc uses
             // relative links.
@@ -736,8 +724,29 @@ impl Step for Rustc {
             }
         }
 
+        // This uses a shared directory so that librustdoc documentation gets
+        // correctly built and merged with the rustc documentation.
+        //
+        // This is needed because rustdoc is built in a different directory from
+        // rustc. rustdoc needs to be able to see everything, for example when
+        // merging the search index, or generating local (relative) links.
+        symlink_dir_force(&builder.config, &out, &out_dir);
+        // Cargo puts proc macros in `target/doc` even if you pass `--target`
+        // explicitly (https://github.com/rust-lang/cargo/issues/7677).
+        let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc");
+        symlink_dir_force(&builder.config, &out, &proc_macro_out_dir);
+
         builder.run(&mut cargo.into());
 
+        if !builder.config.dry_run() {
+            // Sanity check on linked compiler crates
+            for krate in &*self.crates {
+                let dir_name = krate.replace("-", "_");
+                // Making sure the directory exists and is not empty.
+                assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some());
+            }
+        }
+
         if builder.paths.iter().any(|path| path.ends_with("compiler")) {
             // For `x.py doc compiler --open`, open `rustc_middle` by default.
             let index = out.join("rustc_middle").join("index.html");
@@ -756,10 +765,10 @@ macro_rules! tool_doc {
         $should_run: literal,
         $path: literal,
         $(rustc_tool = $rustc_tool:literal, )?
-        $(in_tree = $in_tree:literal, )?
-        [$($extra_arg: literal),+ $(,)?]
-        $(,)?
-    ) => {
+        $(in_tree = $in_tree:literal ,)?
+        $(is_library = $is_library:expr,)?
+        $(crates = $crates:expr)?
+       ) => {
         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
             target: TargetSelection,
@@ -812,17 +821,6 @@ macro_rules! tool_doc {
                     SourceType::Submodule
                 };
 
-                // Symlink compiler docs to the output directory of rustdoc documentation.
-                let out_dirs = [
-                    builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"),
-                    // Cargo uses a different directory for proc macros.
-                    builder.stage_out(compiler, Mode::ToolRustc).join("doc"),
-                ];
-                for out_dir in out_dirs {
-                    t!(fs::create_dir_all(&out_dir));
-                    symlink_dir_force(&builder.config, &out, &out_dir);
-                }
-
                 // Build cargo command.
                 let mut cargo = prepare_tool_cargo(
                     builder,
@@ -839,9 +837,13 @@ macro_rules! tool_doc {
                 // Only include compiler crates, no dependencies of those, such as `libc`.
                 cargo.arg("--no-deps");
 
-                $(
-                    cargo.arg($extra_arg);
-                )+
+                if false $(|| $is_library)? {
+                    cargo.arg("--lib");
+                }
+
+                $(for krate in $crates {
+                    cargo.arg("-p").arg(krate);
+                })?
 
                 cargo.rustdocflag("--document-private-items");
                 // Since we always pass --document-private-items, there's no need to warn about linking to private items.
@@ -851,62 +853,69 @@ macro_rules! tool_doc {
                 cargo.rustdocflag("--generate-link-to-definition");
                 cargo.rustdocflag("-Zunstable-options");
 
+                let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
+                $(for krate in $crates {
+                    let dir_name = krate.replace("-", "_");
+                    t!(fs::create_dir_all(out_dir.join(&*dir_name)));
+                })?
+
+                // Symlink compiler docs to the output directory of rustdoc documentation.
+                symlink_dir_force(&builder.config, &out, &out_dir);
+                let proc_macro_out_dir = builder.stage_out(compiler, Mode::ToolRustc).join("doc");
+                symlink_dir_force(&builder.config, &out, &proc_macro_out_dir);
+
                 let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target);
                 builder.run(&mut cargo.into());
+
+                if !builder.config.dry_run() {
+                    // Sanity check on linked doc directories
+                    $(for krate in $crates {
+                        let dir_name = krate.replace("-", "_");
+                        // Making sure the directory exists and is not empty.
+                        assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some());
+                    })?
+                }
             }
         }
     }
 }
 
-tool_doc!(
-    Rustdoc,
-    "rustdoc-tool",
-    "src/tools/rustdoc",
-    ["-p", "rustdoc", "-p", "rustdoc-json-types"]
-);
+tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]);
 tool_doc!(
     Rustfmt,
     "rustfmt-nightly",
     "src/tools/rustfmt",
-    ["-p", "rustfmt-nightly", "-p", "rustfmt-config_proc_macro"],
+    crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]
 );
-tool_doc!(Clippy, "clippy", "src/tools/clippy", ["-p", "clippy_utils"]);
-tool_doc!(Miri, "miri", "src/tools/miri", ["-p", "miri"]);
+tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
+tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]);
 tool_doc!(
     Cargo,
     "cargo",
     "src/tools/cargo",
     rustc_tool = false,
     in_tree = false,
-    [
-        "-p",
+    crates = [
         "cargo",
-        "-p",
         "cargo-platform",
-        "-p",
         "cargo-util",
-        "-p",
         "crates-io",
-        "-p",
         "cargo-test-macro",
-        "-p",
         "cargo-test-support",
-        "-p",
         "cargo-credential",
-        "-p",
         "mdman",
         // FIXME: this trips a license check in tidy.
-        // "-p",
         // "resolver-tests",
     ]
 );
-tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]);
+tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, crates = ["tidy"]);
 tool_doc!(
     Bootstrap,
     "bootstrap",
     "src/bootstrap",
     rustc_tool = false,
-    ["--lib", "-p", "bootstrap"]
+    is_library = true,
+    crates = ["bootstrap"]
 );
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 435ebb6df90..04a16443770 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -147,6 +147,15 @@ impl Step for Profile {
     }
 
     fn run(self, builder: &Builder<'_>) {
+        // During ./x.py setup once you select the codegen profile.
+        // The submodule will be downloaded. It does not work in the
+        // tarball case since they don't include Git and submodules
+        // are already included.
+        if !builder.rust_info().is_from_tarball() {
+            if self == Profile::Codegen {
+                builder.update_submodule(&Path::new("src/llvm-project"));
+            }
+        }
         setup(&builder.build.config, self)
     }
 }
@@ -469,7 +478,8 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
         assert!(output.status.success(), "failed to run `git`");
         PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
     }));
-    let dst = git.join("hooks").join("pre-push");
+    let hooks_dir = git.join("hooks");
+    let dst = hooks_dir.join("pre-push");
     if dst.exists() {
         // The git hook has already been set up, or the user already has a custom hook.
         return Ok(());
@@ -486,6 +496,10 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
         println!("Ok, skipping installation!");
         return Ok(());
     }
+    if !hooks_dir.exists() {
+        // We need to (try to) create the hooks directory first.
+        let _ = fs::create_dir(hooks_dir);
+    }
     let src = config.src.join("src").join("etc").join("pre-push.sh");
     match fs::hard_link(src, &dst) {
         Err(e) => {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index e2b515a3086..c034e5c9d69 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1305,6 +1305,47 @@ macro_rules! test_definitions {
     };
 }
 
+/// Declares an alias for running the [`Coverage`] tests in only one mode.
+/// Adapted from [`test_definitions`].
+macro_rules! coverage_test_alias {
+    ($name:ident {
+        alias_and_mode: $alias_and_mode:expr,
+        default: $default:expr,
+        only_hosts: $only_hosts:expr $(,)?
+    }) => {
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+        pub struct $name {
+            pub compiler: Compiler,
+            pub target: TargetSelection,
+        }
+
+        impl $name {
+            const MODE: &'static str = $alias_and_mode;
+        }
+
+        impl Step for $name {
+            type Output = ();
+            const DEFAULT: bool = $default;
+            const ONLY_HOSTS: bool = $only_hosts;
+
+            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+                run.alias($alias_and_mode)
+            }
+
+            fn make_run(run: RunConfig<'_>) {
+                let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
+
+                run.builder.ensure($name { compiler, target: run.target });
+            }
+
+            fn run(self, builder: &Builder<'_>) {
+                Coverage { compiler: self.compiler, target: self.target }
+                    .run_unified_suite(builder, Self::MODE)
+            }
+        }
+    };
+}
+
 default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" });
 
 default_test!(RunPassValgrind {
@@ -1349,17 +1390,70 @@ host_test!(RunMakeFullDeps {
 
 default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" });
 
-default_test!(CoverageMap {
-    path: "tests/coverage-map",
-    mode: "coverage-map",
-    suite: "coverage-map"
+/// Custom test step that is responsible for running the coverage tests
+/// in multiple different modes.
+///
+/// Each individual mode also has its own alias that will run the tests in
+/// just that mode.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Coverage {
+    pub compiler: Compiler,
+    pub target: TargetSelection,
+}
+
+impl Coverage {
+    const PATH: &'static str = "tests/coverage";
+    const SUITE: &'static str = "coverage";
+
+    fn run_unified_suite(&self, builder: &Builder<'_>, mode: &'static str) {
+        builder.ensure(Compiletest {
+            compiler: self.compiler,
+            target: self.target,
+            mode,
+            suite: Self::SUITE,
+            path: Self::PATH,
+            compare_mode: None,
+        })
+    }
+}
+
+impl Step for Coverage {
+    type Output = ();
+    const DEFAULT: bool = false;
+    const ONLY_HOSTS: bool = false;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.suite_path(Self::PATH)
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
+
+        run.builder.ensure(Coverage { compiler, target: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        self.run_unified_suite(builder, CoverageMap::MODE);
+        self.run_unified_suite(builder, CoverageRun::MODE);
+    }
+}
+
+// Aliases for running the coverage tests in only one mode.
+coverage_test_alias!(CoverageMap {
+    alias_and_mode: "coverage-map",
+    default: true,
+    only_hosts: false,
+});
+coverage_test_alias!(CoverageRun {
+    alias_and_mode: "coverage-run",
+    default: true,
+    only_hosts: true,
 });
 
-host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" });
-host_test!(RunCoverageRustdoc {
-    path: "tests/run-coverage-rustdoc",
-    mode: "run-coverage",
-    suite: "run-coverage-rustdoc"
+host_test!(CoverageRunRustdoc {
+    path: "tests/coverage-run-rustdoc",
+    mode: "coverage-run",
+    suite: "coverage-run-rustdoc"
 });
 
 // For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
@@ -1546,7 +1640,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             || (mode == "ui" && is_rustdoc)
             || mode == "js-doc-test"
             || mode == "rustdoc-json"
-            || suite == "run-coverage-rustdoc"
+            || suite == "coverage-run-rustdoc"
         {
             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
         }
@@ -1568,7 +1662,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             cmd.arg("--coverage-dump-path").arg(coverage_dump);
         }
 
-        if mode == "run-coverage" {
+        if mode == "coverage-run" {
             // The demangler doesn't need the current compiler, so we can avoid
             // unnecessary rebuilds by using the bootstrap compiler instead.
             let rust_demangler = builder
@@ -1760,11 +1854,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             }
 
             if !builder.config.dry_run()
-                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage")
+                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "coverage-run")
             {
                 // The llvm/bin directory contains many useful cross-platform
                 // tools. Pass the path to run-make tests so they can use them.
-                // (The run-coverage tests also need these tools to process
+                // (The coverage-run tests also need these tools to process
                 // coverage reports.)
                 let llvm_bin_path = llvm_config
                     .parent()
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 44cdbe38de3..1b6ba89aadd 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -727,8 +727,9 @@ impl<'a> Builder<'a> {
                 test::Tidy,
                 test::Ui,
                 test::RunPassValgrind,
+                test::Coverage,
                 test::CoverageMap,
-                test::RunCoverage,
+                test::CoverageRun,
                 test::MirOpt,
                 test::Codegen,
                 test::CodegenUnits,
@@ -739,7 +740,7 @@ impl<'a> Builder<'a> {
                 test::CodegenCranelift,
                 test::CodegenGCC,
                 test::Rustdoc,
-                test::RunCoverageRustdoc,
+                test::CoverageRunRustdoc,
                 test::Pretty,
                 test::Crate,
                 test::CrateLibrustc,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f56e46010f3..2eb5d06bcb3 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -19,6 +19,7 @@ use std::process::Command;
 use std::str::FromStr;
 
 use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
+use crate::core::build_steps::llvm;
 use crate::core::config::flags::{Color, Flags, Warnings};
 use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::channel::{self, GitInfo};
@@ -1072,6 +1073,7 @@ impl Config {
         config.bindir = "bin".into();
         config.dist_include_mingw_linker = true;
         config.dist_compression_profile = "fast".into();
+        config.rustc_parallel = true;
 
         config.stdout_is_tty = std::io::stdout().is_terminal();
         config.stderr_is_tty = std::io::stderr().is_terminal();
@@ -1429,7 +1431,9 @@ impl Config {
             set(&mut config.use_lld, rust.use_lld);
             set(&mut config.lld_enabled, rust.lld);
             set(&mut config.llvm_tools_enabled, rust.llvm_tools);
-            config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
+            config.rustc_parallel = rust
+                .parallel_compiler
+                .unwrap_or(config.channel == "dev" || config.channel == "nightly");
             config.rustc_default_linker = rust.default_linker;
             config.musl_root = rust.musl_root.map(PathBuf::from);
             config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
@@ -1527,17 +1531,7 @@ impl Config {
             config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
 
             let asserts = llvm_assertions.unwrap_or(false);
-            config.llvm_from_ci = match llvm.download_ci_llvm {
-                Some(StringOrBool::String(s)) => {
-                    assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm");
-                    crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
-                }
-                Some(StringOrBool::Bool(b)) => b,
-                None => {
-                    config.channel == "dev"
-                        && crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
-                }
-            };
+            config.llvm_from_ci = config.parse_download_ci_llvm(llvm.download_ci_llvm, asserts);
 
             if config.llvm_from_ci {
                 // None of the LLVM options, except assertions, are supported
@@ -2101,6 +2095,94 @@ impl Config {
 
         Some(commit.to_string())
     }
+
+    fn parse_download_ci_llvm(
+        &self,
+        download_ci_llvm: Option<StringOrBool>,
+        asserts: bool,
+    ) -> bool {
+        match download_ci_llvm {
+            None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts),
+            Some(StringOrBool::Bool(b)) => b,
+            Some(StringOrBool::String(s)) if s == "if-available" => {
+                llvm::is_ci_llvm_available(&self, asserts)
+            }
+            Some(StringOrBool::String(s)) if s == "if-unchanged" => {
+                // Git is needed to track modifications here, but tarball source is not available.
+                // If not modified here or built through tarball source, we maintain consistency
+                // with '"if available"'.
+                if !self.rust_info.is_from_tarball()
+                    && self
+                        .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
+                        .is_none()
+                {
+                    // there are some untracked changes in the the given paths.
+                    false
+                } else {
+                    llvm::is_ci_llvm_available(&self, asserts)
+                }
+            }
+            Some(StringOrBool::String(other)) => {
+                panic!("unrecognized option for download-ci-llvm: {:?}", other)
+            }
+        }
+    }
+
+    /// Returns the last commit in which any of `modified_paths` were changed,
+    /// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
+    pub fn last_modified_commit(
+        &self,
+        modified_paths: &[&str],
+        option_name: &str,
+        if_unchanged: bool,
+    ) -> Option<String> {
+        // Handle running from a directory other than the top level
+        let top_level = output(self.git().args(&["rev-parse", "--show-toplevel"]));
+        let top_level = top_level.trim_end();
+
+        // Look for a version to compare to based on the current commit.
+        // Only commits merged by bors will have CI artifacts.
+        let merge_base = output(
+            self.git()
+                .arg("rev-list")
+                .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
+                .args(&["-n1", "--first-parent", "HEAD"]),
+        );
+        let commit = merge_base.trim_end();
+        if commit.is_empty() {
+            println!("error: could not find commit hash for downloading components from CI");
+            println!("help: maybe your repository history is too shallow?");
+            println!("help: consider disabling `{option_name}`");
+            println!("help: or fetch enough history to include one upstream commit");
+            crate::exit!(1);
+        }
+
+        // Warn if there were changes to the compiler or standard library since the ancestor commit.
+        let mut git = self.git();
+        git.args(&["diff-index", "--quiet", &commit, "--"]);
+
+        for path in modified_paths {
+            git.arg(format!("{top_level}/{path}"));
+        }
+
+        let has_changes = !t!(git.status()).success();
+        if has_changes {
+            if if_unchanged {
+                if self.verbose > 0 {
+                    println!(
+                        "warning: saw changes to one of {modified_paths:?} since {commit}; \
+                            ignoring `{option_name}`"
+                    );
+                }
+                return None;
+            }
+            println!(
+                "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
+            );
+        }
+
+        Some(commit.to_string())
+    }
 }
 
 fn set<T>(field: &mut T, val: Option<T>) {
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index d7f49a6d11b..fc3413a3c81 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -77,7 +77,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
 ///
 /// If you make any major changes (such as adding new values or changing default values), please
 /// ensure that the associated PR ID is added to the end of this list.
-pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998];
+pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435, 116881];
 
 /// Extra --check-cfg to add when building
 /// (Mode restriction, config name, config values (if any))
@@ -1197,11 +1197,10 @@ impl Build {
             .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
             .collect::<Vec<String>>();
 
-        // If we're compiling on macOS then we add a few unconditional flags
-        // indicating that we want libc++ (more filled out than libstdc++) and
-        // we want to compile for 10.7. This way we can ensure that
+        // If we're compiling C++ on macOS then we add a flag indicating that
+        // we want libc++ (more filled out than libstdc++), ensuring that
         // LLVM/etc are all properly compiled.
-        if target.contains("apple-darwin") {
+        if matches!(c, CLang::Cxx) && target.contains("apple-darwin") {
             base.push("-stdlib=libc++".into());
         }
 
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
index 56ee348a337..1d9568702cc 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
@@ -4,7 +4,7 @@ set -ex
 
 source shared.sh
 
-LLVM=llvmorg-17.0.2
+LLVM=llvmorg-17.0.4
 
 mkdir llvm-project
 cd llvm-project
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
index 3b3ec5da74b..e939a5d7eac 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
@@ -3,7 +3,8 @@ set -ex
 
 source shared.sh
 
-GCC=8.5.0
+# Note: in the future when bumping to version 10.1.0, also take care of the sed block below.
+GCC=9.5.0
 
 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf -
 cd gcc-$GCC
@@ -22,6 +23,11 @@ cd gcc-$GCC
 # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
 # instead here.
 #
+# Note: in version 10.1.0, the URL used in `download_prerequisites` has changed from using FTP to
+# using HTTP. When bumping to that gcc version, we can likely remove the sed replacement below, or
+# the expression will need to be updated. That new URL is available at:
+# https://github.com/gcc-mirror/gcc/blob/6e6e3f144a33ae504149dc992453b4f6dea12fdb/contrib/download_prerequisites#L35
+#
 sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites
 
 ./contrib/download_prerequisites
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
new file mode 100644
index 00000000000..e983edf205c
--- /dev/null
+++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
@@ -0,0 +1,16 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "r-efi"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "575fc2d9b3da54adbdfaddf6eca48fec256d977c8630a1750b8991347d1ac911"
+
+[[package]]
+name = "uefi_qemu_test"
+version = "0.0.0"
+dependencies = [
+ "r-efi",
+]
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index a2891ef9563..cedbc0390f8 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -302,6 +302,7 @@ docker \
   --env DIST_TRY_BUILD \
   --env PR_CI_JOB \
   --env OBJDIR_ON_HOST="$objdir" \
+  --env CODEGEN_BACKENDS \
   --init \
   --rm \
   rust-ci \
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 31ef55216b9..ce0dd6018af 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -98,8 +98,8 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
   if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
   elif [ "$DEPLOY_ALT" != "" ]; then
-    if [ "$NO_PARALLEL_COMPILER" = "" ]; then
-      RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler"
+    if [ "$ALT_PARALLEL_COMPILER" = "" ]; then
+      RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler=false"
     fi
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions"
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir"
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 16fd3c06d9e558dae2d52000818274ae70c9e90
+Subproject cd8193e972f61b92117095fc73b67af767b4d6b
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 6709beeb7d0fbc5ffc91ac4893a24434123b9bf
+Subproject 311b84962016b28c75525c86e7b3f49fd9101a3
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject b0ee9ec8fa59a6c7620165e061f4747202377a6
+Subproject 77dbe5782b2488af3bb489ad702eaff438f465b
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 8b4d673d831..1b27b77b3e6 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -41,6 +41,7 @@
     - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
     - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
     - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
+    - [powerpc64-ibm-aix](platform-support/aix.md)
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 6a979869a59..907e9c59f31 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -310,7 +310,7 @@ target | std | host | notes
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
-`powerpc64-ibm-aix` | ? |  | 64-bit AIX (7.2 and newer)
+[`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
 `riscv32im-unknown-none-elf` | * |  | Bare RISC-V (RV32IM ISA)
diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md
new file mode 100644
index 00000000000..c3ce71a1835
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aix.md
@@ -0,0 +1,26 @@
+# `powerpc64-ibm-aix`
+
+**Tier: 3**
+
+Rust for AIX operating system, currently only 64-bit PowerPC is supported.
+
+## Target maintainers
+
+- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises
+- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq
+
+## Requirements
+
+This target supports host tools, std and alloc. This target cannot be cross-compiled as for now, mainly because of the unavailability of system linker on other platforms.
+
+Binary built for this target is expected to run on Power7 or newer CPU, and AIX 7.2 or newer version.
+
+Binary format of this platform is [XCOFF](https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format). Archive file format is ['AIX big format'](https://www.ibm.com/docs/en/aix/7.2?topic=formats-ar-file-format-big).
+
+## Testing
+
+This target supports running test suites natively, but it's not available to cross-compile and execute in emulator.
+
+## Interoperability with C code
+
+This target supports C code. C code compiled by XL, Open XL and Clang are compatible with Rust. Typical triple of AIX on 64-bit PowerPC of these compilers are also `powerpc64-ibm-aix`.
diff --git a/src/etc/test-float-parse/Cargo.lock b/src/etc/test-float-parse/Cargo.lock
new file mode 100644
index 00000000000..3f60423fed3
--- /dev/null
+++ b/src/etc/test-float-parse/Cargo.lock
@@ -0,0 +1,75 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.147"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "test-float-parse"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index 6d7b227d0ad..a045be956ac 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
 resolver = "1"
 
 [dependencies]
-rand = "0.4"
+rand = "0.8"
 
 [lib]
 name = "test_float_parse"
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 013814b1f7d..974ba1e3bd9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -599,7 +599,7 @@ fn build_module_items(
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
                     name: None,
-                    attrs: Box::new(clean::Attributes::default()),
+                    attrs: Box::default(),
                     // We can use the item's `DefId` directly since the only information ever used
                     // from it is `DefId.krate`.
                     item_id: ItemId::DefId(did),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e6e2d60f2e5..1b7ca7bf7dd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2534,7 +2534,8 @@ fn clean_generic_args<'tcx>(
                     }
                     hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                     hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
-                    // FIXME(effects): This will still emit `<true>` for non-const impls of const traits
+                    // Checking for `#[rustc_host]` on the `AnonConst`  not only accounts for the case
+                    // where the argument is `host` but for all possible cases (e.g., `true`, `false`).
                     hir::GenericArg::Const(ct)
                         if cx.tcx.has_attr(ct.value.def_id, sym::rustc_host) =>
                     {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index a718cb37d89..88ee4e3a2ab 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1327,6 +1327,7 @@ impl WherePredicate {
 pub(crate) enum GenericParamDefKind {
     Lifetime { outlives: ThinVec<Lifetime> },
     Type { did: DefId, bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
+    // Option<Box<String>> makes this type smaller than `Option<String>` would.
     Const { ty: Box<Type>, default: Option<Box<String>>, is_host_effect: bool },
 }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index dea7bfaf7e2..9ff00c1946f 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -124,11 +124,7 @@ pub(crate) fn ty_args_to_args<'tcx>(
             )))
         }
         GenericArgKind::Const(ct) => {
-            // FIXME(effects): this relies on the host effect being called `host`, which users could also name
-            // their const generics.
-            // FIXME(effects): this causes `host = true` and `host = false` generics to also be emitted.
-            if let ty::ConstKind::Param(p) = ct.kind()
-                && p.name == sym::host
+            if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind
             {
                 return None;
             }
@@ -588,7 +584,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
 pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
 pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
-    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
+    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').filter(|c| !c.is_empty()).next().unwrap());
 
 /// Render a sequence of macro arms in a format suitable for displaying to the user
 /// as part of an item declaration.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index aa728c26afc..2807dfed072 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1750,7 +1750,7 @@ pub(crate) fn markdown_links<'md, R>(
         }
         // do not actually include braces in the span
         let range = (open_brace + 1)..close_brace;
-        MarkdownLinkRange::Destination(range.clone())
+        MarkdownLinkRange::Destination(range)
     };
 
     let span_for_offset_forward = |span: Range<usize>, open: u8, close: u8| {
@@ -1786,7 +1786,7 @@ pub(crate) fn markdown_links<'md, R>(
         }
         // do not actually include braces in the span
         let range = (open_brace + 1)..close_brace;
-        MarkdownLinkRange::Destination(range.clone())
+        MarkdownLinkRange::Destination(range)
     };
 
     let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 3e58dd96ed9..d2c7c578c08 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -356,15 +356,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
 
             let content = format!(
                 "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>",
-                krates
-                    .iter()
-                    .map(|s| {
-                        format!(
-                            "<li><a href=\"{trailing_slash}index.html\">{s}</a></li>",
-                            trailing_slash = ensure_trailing_slash(s),
-                        )
-                    })
-                    .collect::<String>()
+                krates.iter().format_with("", |k, f| {
+                    f(&format_args!(
+                        "<li><a href=\"{trailing_slash}index.html\">{k}</a></li>",
+                        trailing_slash = ensure_trailing_slash(k),
+                    ))
+                })
             );
             let v = layout::render(&shared.layout, &page, "", content, &shared.style_files);
             shared.fs.write(dst, v)?;
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index ebf817673bf..3f6147bb916 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -10,7 +10,6 @@
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {# #}
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {# #}
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {# #}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_bold}}"> {# #}
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {# #}
     <link rel="stylesheet" {#+ #}
           href="{{static_root_path|safe}}{{files.normalize_css}}"> {# #}
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 79fc599e176..00d15a3ca8d 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -25,91 +25,85 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                 Some(sp) => sp,
                 None => item.attr_span(tcx),
             };
-            tcx.struct_span_lint_hir(
-                crate::lint::INVALID_HTML_TAGS,
-                hir_id,
-                sp,
-                msg.to_string(),
-                |lint| {
-                    use rustc_lint_defs::Applicability;
-                    // If a tag looks like `<this>`, it might actually be a generic.
-                    // We don't try to detect stuff `<like, this>` because that's not valid HTML,
-                    // and we don't try to detect stuff `<like this>` because that's not valid Rust.
-                    let mut generics_end = range.end;
-                    if let Some(Some(mut generics_start)) = (is_open_tag
-                        && dox[..generics_end].ends_with('>'))
-                    .then(|| extract_path_backwards(&dox, range.start))
+            tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
+                use rustc_lint_defs::Applicability;
+                // If a tag looks like `<this>`, it might actually be a generic.
+                // We don't try to detect stuff `<like, this>` because that's not valid HTML,
+                // and we don't try to detect stuff `<like this>` because that's not valid Rust.
+                let mut generics_end = range.end;
+                if let Some(Some(mut generics_start)) = (is_open_tag
+                    && dox[..generics_end].ends_with('>'))
+                .then(|| extract_path_backwards(&dox, range.start))
+                {
+                    while generics_start != 0
+                        && generics_end < dox.len()
+                        && dox.as_bytes()[generics_start - 1] == b'<'
+                        && dox.as_bytes()[generics_end] == b'>'
                     {
-                        while generics_start != 0
-                            && generics_end < dox.len()
-                            && dox.as_bytes()[generics_start - 1] == b'<'
-                            && dox.as_bytes()[generics_end] == b'>'
-                        {
-                            generics_end += 1;
-                            generics_start -= 1;
-                            if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
-                                generics_start = new_start;
-                            }
-                            if let Some(new_end) = extract_path_forward(&dox, generics_end) {
-                                generics_end = new_end;
-                            }
+                        generics_end += 1;
+                        generics_start -= 1;
+                        if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
+                            generics_start = new_start;
                         }
                         if let Some(new_end) = extract_path_forward(&dox, generics_end) {
                             generics_end = new_end;
                         }
-                        let generics_sp = match source_span_for_markdown_range(
-                            tcx,
-                            &dox,
-                            &(generics_start..generics_end),
-                            &item.attrs.doc_strings,
-                        ) {
-                            Some(sp) => sp,
-                            None => item.attr_span(tcx),
-                        };
-                        // Sometimes, we only extract part of a path. For example, consider this:
-                        //
-                        //     <[u32] as IntoIter<u32>>::Item
-                        //                       ^^^^^ unclosed HTML tag `u32`
-                        //
-                        // We don't have any code for parsing fully-qualified trait paths.
-                        // In theory, we could add it, but doing it correctly would require
-                        // parsing the entire path grammar, which is problematic because of
-                        // overlap between the path grammar and Markdown.
-                        //
-                        // The example above shows that ambiguity. Is `[u32]` intended to be an
-                        // intra-doc link to the u32 primitive, or is it intended to be a slice?
-                        //
-                        // If the below conditional were removed, we would suggest this, which is
-                        // not what the user probably wants.
-                        //
-                        //     <[u32] as `IntoIter<u32>`>::Item
-                        //
-                        // We know that the user actually wants to wrap the whole thing in a code
-                        // block, but the only reason we know that is because `u32` does not, in
-                        // fact, implement IntoIter. If the example looks like this:
-                        //
-                        //     <[Vec<i32>] as IntoIter<i32>::Item
-                        //
-                        // The ideal fix would be significantly different.
-                        if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
-                            || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
-                        {
-                            return lint;
-                        }
-                        // multipart form is chosen here because ``Vec<i32>`` would be confusing.
-                        lint.multipart_suggestion(
-                            "try marking as source code",
-                            vec![
-                                (generics_sp.shrink_to_lo(), String::from("`")),
-                                (generics_sp.shrink_to_hi(), String::from("`")),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
                     }
+                    if let Some(new_end) = extract_path_forward(&dox, generics_end) {
+                        generics_end = new_end;
+                    }
+                    let generics_sp = match source_span_for_markdown_range(
+                        tcx,
+                        &dox,
+                        &(generics_start..generics_end),
+                        &item.attrs.doc_strings,
+                    ) {
+                        Some(sp) => sp,
+                        None => item.attr_span(tcx),
+                    };
+                    // Sometimes, we only extract part of a path. For example, consider this:
+                    //
+                    //     <[u32] as IntoIter<u32>>::Item
+                    //                       ^^^^^ unclosed HTML tag `u32`
+                    //
+                    // We don't have any code for parsing fully-qualified trait paths.
+                    // In theory, we could add it, but doing it correctly would require
+                    // parsing the entire path grammar, which is problematic because of
+                    // overlap between the path grammar and Markdown.
+                    //
+                    // The example above shows that ambiguity. Is `[u32]` intended to be an
+                    // intra-doc link to the u32 primitive, or is it intended to be a slice?
+                    //
+                    // If the below conditional were removed, we would suggest this, which is
+                    // not what the user probably wants.
+                    //
+                    //     <[u32] as `IntoIter<u32>`>::Item
+                    //
+                    // We know that the user actually wants to wrap the whole thing in a code
+                    // block, but the only reason we know that is because `u32` does not, in
+                    // fact, implement IntoIter. If the example looks like this:
+                    //
+                    //     <[Vec<i32>] as IntoIter<i32>::Item
+                    //
+                    // The ideal fix would be significantly different.
+                    if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
+                        || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
+                    {
+                        return lint;
+                    }
+                    // multipart form is chosen here because ``Vec<i32>`` would be confusing.
+                    lint.multipart_suggestion(
+                        "try marking as source code",
+                        vec![
+                            (generics_sp.shrink_to_lo(), String::from("`")),
+                            (generics_sp.shrink_to_hi(), String::from("`")),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
 
-                    lint
-                },
-            );
+                lint
+            });
         };
 
         let mut tags = Vec::new();
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 0c15bf5f764..472781e7d22 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -87,7 +87,7 @@ fn check_redundant_explicit_link<'md>(
                 let link_data = collect_link_data(&mut offset_iter);
 
                 if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
-                    if &link_data.display_link.replace("`", "") != resolvable_link {
+                    if &link_data.display_link.replace('`', "") != resolvable_link {
                         // Skips if display link does not match to actual
                         // resolvable link, usually happens if display link
                         // has several segments, e.g.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 2c795ebb214..aed6796fa13 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -266,6 +266,29 @@ impl Builder {
             // channel-rust-1.XX.toml
             let major_minor = rust_version.split('.').take(2).collect::<Vec<_>>().join(".");
             self.write_channel_files(&major_minor, &manifest);
+        } else if channel == "beta" {
+            // channel-rust-1.XX.YY-beta.Z.toml
+            let rust_version = self
+                .versions
+                .version(&PkgType::Rust)
+                .expect("missing Rust tarball")
+                .version
+                .expect("missing Rust version")
+                .split(' ')
+                .next()
+                .unwrap()
+                .to_string();
+            self.write_channel_files(&rust_version, &manifest);
+
+            // channel-rust-1.XX.YY-beta.toml
+            let major_minor_patch_beta =
+                rust_version.split('.').take(3).collect::<Vec<_>>().join(".");
+            self.write_channel_files(&major_minor_patch_beta, &manifest);
+
+            // channel-rust-1.XX-beta.toml
+            let major_minor_beta =
+                format!("{}-beta", rust_version.split('.').take(2).collect::<Vec<_>>().join("."));
+            self.write_channel_files(&major_minor_beta, &manifest);
         }
 
         if let Some(path) = std::env::var_os("BUILD_MANIFEST_SHIPPED_FILES_PATH") {
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject b4d18d4bd3db6d872892f6c87c51a02999b8080
+Subproject 7046d992f9f32ba209a8079f662ebccf9da8de2
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index ce93aea2136..152248afc90 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -7,7 +7,7 @@ use rustc_ast::LitIntType;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::{
-    ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
+    ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, CaptureBy
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -479,6 +479,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 movability,
                 ..
             }) => {
+                let capture_clause = match capture_clause {
+                    CaptureBy::Value { .. } => "Value { .. }",
+                    CaptureBy::Ref => "Ref",
+                };
+
                 let movability = OptionPat::new(movability.map(|m| format!("Movability::{m:?}")));
 
                 let ret_ty = match fn_decl.output {
@@ -487,7 +492,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 };
 
                 bind!(self, fn_decl, body_id);
-                kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})");
+                kind!("Closure(CaptureBy::{capture_clause}, {fn_decl}, {body_id}, _, {movability})");
                 chain!(self, "let {ret_ty} = {fn_decl}.output");
                 self.body(body_id);
             },
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout
index eb3e5189c82..140300a1673 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui/author/blocks.stdout
@@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind
 {
     // report your lint here
 }
-if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
+if let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl, body_id, _, None) = expr.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl.output
     && expr1 = &cx.tcx.hir().body(body_id).value
-    && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
+    && let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl1.output
     && expr2 = &cx.tcx.hir().body(body_id1).value
     && let ExprKind::Block(block, None) = expr2.kind
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
index e1b95aa5776..5c277f925a8 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -9,12 +9,12 @@ fn repeat() -> ! {
 }
 
 pub fn f(x: Ordering) {
+    #[deny(non_exhaustive_omitted_patterns)]
     match x {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
         Ordering::AcqRel | Ordering::SeqCst => repeat(),
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => repeat(),
     }
 }
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 0e1bf0c6c2d..bdf8c35e73b 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -67,7 +67,7 @@ string_enum! {
         MirOpt => "mir-opt",
         Assembly => "assembly",
         CoverageMap => "coverage-map",
-        RunCoverage => "run-coverage",
+        CoverageRun => "coverage-run",
     }
 }
 
@@ -78,7 +78,7 @@ impl Default for Mode {
 }
 
 impl Mode {
-    pub fn disambiguator(self) -> &'static str {
+    pub fn aux_dir_disambiguator(self) -> &'static str {
         // Pretty-printing tests could run concurrently, and if they do,
         // they need to keep their output segregated.
         match self {
@@ -86,6 +86,15 @@ impl Mode {
             _ => "",
         }
     }
+
+    pub fn output_dir_disambiguator(self) -> &'static str {
+        // Coverage tests use the same test files for multiple test modes,
+        // so each mode should have a separate output directory.
+        match self {
+            CoverageMap | CoverageRun => self.to_str(),
+            _ => "",
+        }
+    }
 }
 
 string_enum! {
@@ -699,6 +708,7 @@ pub fn output_testname_unique(
     let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
     let debugger = config.debugger.as_ref().map_or("", |m| m.to_str());
     PathBuf::from(&testpaths.file.file_stem().unwrap())
+        .with_extra_extension(config.mode.output_dir_disambiguator())
         .with_extra_extension(revision.unwrap_or(""))
         .with_extra_extension(mode)
         .with_extra_extension(debugger)
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 948439d6e79..d6516cff63f 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -911,11 +911,11 @@ pub fn make_test_description<R: Read>(
     let mut should_fail = false;
 
     let extra_directives: &[&str] = match config.mode {
-        // The run-coverage tests are treated as having these extra directives,
+        // The coverage-run tests are treated as having these extra directives,
         // without needing to specify them manually in every test file.
         // (Some of the comments below have been copied over from
         // `tests/run-make/coverage-reports/Makefile`, which no longer exists.)
-        Mode::RunCoverage => {
+        Mode::CoverageRun => {
             &[
                 "needs-profiler-support",
                 // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index e74d66a8599..63e8ba7c79f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -6,7 +6,7 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs
 use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
 use crate::common::{Config, TestPaths};
-use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind};
+use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind};
 use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::compute_diff::{write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
@@ -257,7 +257,7 @@ impl<'test> TestCx<'test> {
             Assembly => self.run_assembly_test(),
             JsDocTest => self.run_js_doc_test(),
             CoverageMap => self.run_coverage_map_test(),
-            RunCoverage => self.run_coverage_test(),
+            CoverageRun => self.run_coverage_run_test(),
         }
     }
 
@@ -510,7 +510,7 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn run_coverage_test(&self) {
+    fn run_coverage_run_test(&self) {
         let should_run = self.run_if_enabled();
         let proc_res = self.compile_test(should_run, Emit::None);
 
@@ -549,7 +549,7 @@ impl<'test> TestCx<'test> {
         let mut profraw_paths = vec![profraw_path];
         let mut bin_paths = vec![self.make_exe_name()];
 
-        if self.config.suite == "run-coverage-rustdoc" {
+        if self.config.suite == "coverage-run-rustdoc" {
             self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths);
         }
 
@@ -2193,7 +2193,7 @@ impl<'test> TestCx<'test> {
             || self.is_vxworks_pure_static()
             || self.config.target.contains("bpf")
             || !self.config.target_cfg().dynamic_linking
-            || self.config.mode == RunCoverage
+            || matches!(self.config.mode, CoverageMap | CoverageRun)
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -2395,7 +2395,7 @@ impl<'test> TestCx<'test> {
                     }
                 }
                 DebugInfo => { /* debuginfo tests must be unoptimized */ }
-                CoverageMap | RunCoverage => {
+                CoverageMap | CoverageRun => {
                     // Coverage mappings and coverage reports are affected by
                     // optimization level, so they ignore the optimize-tests
                     // setting and set an optimization level in their mode's
@@ -2478,12 +2478,12 @@ impl<'test> TestCx<'test> {
                 // by `compile-flags`.
                 rustc.arg("-Copt-level=2");
             }
-            RunCoverage => {
+            CoverageRun => {
                 rustc.arg("-Cinstrument-coverage");
                 // Coverage reports are sometimes sensitive to optimizations,
-                // and the current snapshots assume no optimization unless
+                // and the current snapshots assume `opt-level=2` unless
                 // overridden by `compile-flags`.
-                rustc.arg("-Copt-level=0");
+                rustc.arg("-Copt-level=2");
             }
             RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake
             | CodegenUnits | JsDocTest | Assembly => {
@@ -2720,7 +2720,7 @@ impl<'test> TestCx<'test> {
     fn aux_output_dir_name(&self) -> PathBuf {
         self.output_base_dir()
             .join("auxiliary")
-            .with_extra_extension(self.config.mode.disambiguator())
+            .with_extra_extension(self.config.mode.aux_dir_disambiguator())
     }
 
     /// Generates a unique name for the test, such as `testname.revision.mode`.
@@ -3962,7 +3962,7 @@ impl<'test> TestCx<'test> {
             // And finally, compile the fixed code and make sure it both
             // succeeds and has no diagnostics.
             let rustc = self.make_compile_args(
-                &self.testpaths.file.with_extension(UI_FIXED),
+                &self.expected_output_path(UI_FIXED),
                 TargetLocation::ThisFile(self.make_exe_name()),
                 emit_metadata,
                 AllowUnused::No,
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index ca2bb80bd26..f90fd1f7fc5 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -223,9 +223,10 @@ degree documented below):
 - All Rust [Tier 1 targets](https://doc.rust-lang.org/rustc/platform-support.html) are supported by
   Miri. They are all checked on Miri's CI, and some (at least one per OS) are even checked on every
   Rust PR, so the shipped Miri should always work on these targets.
-- We also support `s390x-unknown-linux-gnu` as our "big-endian target of choice".
+- `aarch64-apple-darwin` is supported.
+- `s390x-unknown-linux-gnu` is supported as our "big-endian target of choice".
 - For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
-  make no promises.
+  make no promises and we don't run tests for such targets.
 - For targets on other operating systems, even basic operations such as printing to the standard
   output might not work, and Miri might fail before even reaching the `main` function.
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 60ae5d12598..2beb3bfef9e 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-2e4e2a8f288f642cafcc41fff211955ceddc453d
+3aaa0f57b7b877ef58532a8de075d1e5a79142bf
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 531128ed2ec..cd628444fed 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -241,7 +241,7 @@ fn run_compiler(
     mut args: Vec<String>,
     target_crate: bool,
     callbacks: &mut (dyn rustc_driver::Callbacks + Send),
-    using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>
+    using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>,
 ) -> ! {
     if target_crate {
         // Miri needs a custom sysroot for target crates.
@@ -275,7 +275,8 @@ fn run_compiler(
     // Invoke compiler, and handle return code.
     let exit_code = rustc_driver::catch_with_exit_code(move || {
         rustc_driver::RunCompiler::new(&args, callbacks)
-            .set_using_internal_features(using_internal_features).run()
+            .set_using_internal_features(using_internal_features)
+            .run()
     });
     std::process::exit(exit_code)
 }
@@ -297,7 +298,8 @@ fn main() {
     // If the environment asks us to actually be rustc, then do that.
     if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
         // Earliest rustc setup.
-        let using_internal_features = rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
+        let using_internal_features =
+            rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
         rustc_driver::init_rustc_env_logger(&handler);
 
         let target_crate = if crate_kind == "target" {
@@ -318,7 +320,8 @@ fn main() {
     }
 
     // Add an ICE bug report hook.
-    let using_internal_features = rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ());
+    let using_internal_features =
+        rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ());
 
     // Init loggers the Miri way.
     init_early_loggers(&handler);
@@ -581,5 +584,10 @@ fn main() {
 
     debug!("rustc arguments: {:?}", rustc_args);
     debug!("crate arguments: {:?}", miri_config.args);
-    run_compiler(rustc_args, /* target_crate: */ true, &mut MiriCompilerCalls { miri_config }, using_internal_features)
+    run_compiler(
+        rustc_args,
+        /* target_crate: */ true,
+        &mut MiriCompilerCalls { miri_config },
+        using_internal_features,
+    )
 }
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 4cab86af886..5d109a7d55c 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -41,7 +41,6 @@
 //! on the data-race detection code.
 
 use std::{
-    borrow::Cow,
     cell::{Cell, Ref, RefCell, RefMut},
     fmt::Debug,
     mem,
@@ -52,7 +51,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir;
 use rustc_span::Span;
-use rustc_target::abi::{Align, Size};
+use rustc_target::abi::{Align, HasDataLayout, Size};
 
 use crate::diagnostics::RacingOp;
 use crate::*;
@@ -194,12 +193,19 @@ struct AtomicMemoryCellClocks {
     size: Size,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum AtomicAccessType {
+    Load(AtomicReadOrd),
+    Store,
+    Rmw,
+}
+
 /// Type of write operation: allocating memory
 /// non-atomic writes and deallocating memory
 /// are all treated as writes for the purpose
 /// of the data-race detector.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum WriteType {
+enum NaWriteType {
     /// Allocate memory.
     Allocate,
 
@@ -212,12 +218,48 @@ enum WriteType {
     /// (Same for `Allocate` above.)
     Deallocate,
 }
-impl WriteType {
-    fn get_descriptor(self) -> &'static str {
+
+impl NaWriteType {
+    fn description(self) -> &'static str {
         match self {
-            WriteType::Allocate => "Allocate",
-            WriteType::Write => "Write",
-            WriteType::Deallocate => "Deallocate",
+            NaWriteType::Allocate => "creating a new allocation",
+            NaWriteType::Write => "non-atomic write",
+            NaWriteType::Deallocate => "deallocation",
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum AccessType {
+    NaRead,
+    NaWrite(NaWriteType),
+    AtomicLoad,
+    AtomicStore,
+    AtomicRmw,
+}
+
+impl AccessType {
+    fn description(self) -> &'static str {
+        match self {
+            AccessType::NaRead => "non-atomic read",
+            AccessType::NaWrite(w) => w.description(),
+            AccessType::AtomicLoad => "atomic load",
+            AccessType::AtomicStore => "atomic store",
+            AccessType::AtomicRmw => "atomic read-modify-write",
+        }
+    }
+
+    fn is_atomic(self) -> bool {
+        match self {
+            AccessType::AtomicLoad | AccessType::AtomicStore | AccessType::AtomicRmw => true,
+            AccessType::NaRead | AccessType::NaWrite(_) => false,
+        }
+    }
+
+    fn is_read(self) -> bool {
+        match self {
+            AccessType::AtomicLoad | AccessType::NaRead => true,
+            AccessType::NaWrite(_) | AccessType::AtomicStore | AccessType::AtomicRmw => false,
         }
     }
 }
@@ -234,7 +276,7 @@ struct MemoryCellClocks {
     /// The type of operation that the write index represents,
     /// either newly allocated memory, a non-atomic write or
     /// a deallocation of memory.
-    write_type: WriteType,
+    write_type: NaWriteType,
 
     /// The vector-clock of all non-atomic reads that happened since the last non-atomic write
     /// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to
@@ -265,7 +307,7 @@ impl MemoryCellClocks {
         MemoryCellClocks {
             read: VClock::default(),
             write: (alloc_index, alloc),
-            write_type: WriteType::Allocate,
+            write_type: NaWriteType::Allocate,
             atomic_ops: None,
         }
     }
@@ -488,7 +530,7 @@ impl MemoryCellClocks {
         &mut self,
         thread_clocks: &mut ThreadClockSet,
         index: VectorIdx,
-        write_type: WriteType,
+        write_type: NaWriteType,
         current_span: Span,
     ) -> Result<(), DataRace> {
         log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, thread_clocks);
@@ -526,7 +568,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         atomic: AtomicReadOrd,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_ref();
-        this.atomic_access_check(place)?;
+        this.atomic_access_check(place, AtomicAccessType::Load(atomic))?;
         // This will read from the last store in the modification order of this location. In case
         // weak memory emulation is enabled, this may not be the store we will pick to actually read from and return.
         // This is fine with StackedBorrow and race checks because they don't concern metadata on
@@ -546,7 +588,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         atomic: AtomicWriteOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        this.atomic_access_check(dest)?;
+        this.atomic_access_check(dest, AtomicAccessType::Store)?;
 
         this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?;
         this.validate_atomic_store(dest, atomic)?;
@@ -558,8 +600,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         this.buffered_atomic_write(val, dest, atomic, val)
     }
 
-    /// Perform an atomic operation on a memory location.
-    fn atomic_op_immediate(
+    /// Perform an atomic RMW operation on a memory location.
+    fn atomic_rmw_op_immediate(
         &mut self,
         place: &MPlaceTy<'tcx, Provenance>,
         rhs: &ImmTy<'tcx, Provenance>,
@@ -568,7 +610,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
-        this.atomic_access_check(place)?;
+        this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
         let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
 
@@ -592,7 +634,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
-        this.atomic_access_check(place)?;
+        this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
         let old = this.allow_data_races_mut(|this| this.read_scalar(place))?;
         this.allow_data_races_mut(|this| this.write_scalar(new, place))?;
@@ -613,7 +655,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
-        this.atomic_access_check(place)?;
+        this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
         let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
         let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
@@ -652,7 +694,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Immediate<Provenance>> {
         use rand::Rng as _;
         let this = self.eval_context_mut();
-        this.atomic_access_check(place)?;
+        this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
         // Failure ordering cannot be stronger than success ordering, therefore first attempt
         // to read with the failure ordering and if successful then try again with the success
@@ -838,48 +880,45 @@ impl VClockAlloc {
         global: &GlobalState,
         thread_mgr: &ThreadManager<'_, '_>,
         mem_clocks: &MemoryCellClocks,
-        action: &str,
-        is_atomic: bool,
+        access: AccessType,
         access_size: Size,
         ptr_dbg: Pointer<AllocId>,
     ) -> InterpResult<'tcx> {
         let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
-        let mut action = Cow::Borrowed(action);
-        let mut involves_non_atomic = true;
+        let mut other_size = None; // if `Some`, this was a size-mismatch race
         let write_clock;
-        let (other_action, other_thread, other_clock) =
+        let (other_access, other_thread, other_clock) =
             // First check the atomic-nonatomic cases. If it looks like multiple
             // cases apply, this one should take precedence, else it might look like
             // we are reporting races between two non-atomic reads.
-            if !is_atomic &&
+            if !access.is_atomic() &&
                 let Some(atomic) = mem_clocks.atomic() &&
                 let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
             {
-                (format!("Atomic Store"), idx, &atomic.write_vector)
-            } else if !is_atomic &&
+                (AccessType::AtomicStore, idx, &atomic.write_vector)
+            } else if !access.is_atomic() &&
                 let Some(atomic) = mem_clocks.atomic() &&
                 let Some(idx) = Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
             {
-                (format!("Atomic Load"), idx, &atomic.read_vector)
+                (AccessType::AtomicLoad, idx, &atomic.read_vector)
             // Then check races with non-atomic writes/reads.
             } else if mem_clocks.write.1 > current_clocks.clock[mem_clocks.write.0] {
                 write_clock = mem_clocks.write();
-                (mem_clocks.write_type.get_descriptor().to_owned(), mem_clocks.write.0, &write_clock)
+                (AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock)
             } else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
-                (format!("Read"), idx, &mem_clocks.read)
+                (AccessType::NaRead, idx, &mem_clocks.read)
             // Finally, mixed-size races.
-            } else if is_atomic && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size {
+            } else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size {
                 // This is only a race if we are not synchronized with all atomic accesses, so find
                 // the one we are not synchronized with.
-                involves_non_atomic = false;
-                action = format!("{}-byte (different-size) {action}", access_size.bytes()).into();
+                other_size = Some(atomic.size);
                 if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
                     {
-                        (format!("{}-byte Atomic Store", atomic.size.bytes()), idx, &atomic.write_vector)
+                        (AccessType::AtomicStore, idx, &atomic.write_vector)
                     } else if let Some(idx) =
                         Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
                     {
-                        (format!("{}-byte Atomic Load", atomic.size.bytes()), idx, &atomic.read_vector)
+                        (AccessType::AtomicLoad, idx, &atomic.read_vector)
                     } else {
                         unreachable!(
                             "Failed to report data-race for mixed-size access: no race found"
@@ -892,18 +931,39 @@ impl VClockAlloc {
         // Load elaborated thread information about the racing thread actions.
         let current_thread_info = global.print_thread_metadata(thread_mgr, current_index);
         let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
+        let involves_non_atomic = !access.is_atomic() || !other_access.is_atomic();
 
         // Throw the data-race detection.
+        let extra = if other_size.is_some() {
+            assert!(!involves_non_atomic);
+            Some("overlapping unsynchronized atomic accesses must use the same access size")
+        } else if access.is_read() && other_access.is_read() {
+            assert!(involves_non_atomic);
+            Some(
+                "overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only",
+            )
+        } else {
+            None
+        };
         Err(err_machine_stop!(TerminationInfo::DataRace {
             involves_non_atomic,
+            extra,
             ptr: ptr_dbg,
             op1: RacingOp {
-                action: other_action.to_string(),
+                action: if let Some(other_size) = other_size {
+                    format!("{}-byte {}", other_size.bytes(), other_access.description())
+                } else {
+                    other_access.description().to_owned()
+                },
                 thread_info: other_thread_info,
                 span: other_clock.as_slice()[other_thread.index()].span_data(),
             },
             op2: RacingOp {
-                action: action.to_string(),
+                action: if other_size.is_some() {
+                    format!("{}-byte {}", access_size.bytes(), access.description())
+                } else {
+                    access.description().to_owned()
+                },
                 thread_info: current_thread_info,
                 span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
             },
@@ -938,8 +998,7 @@ impl VClockAlloc {
                         global,
                         &machine.threads,
                         mem_clocks,
-                        "Read",
-                        /* is_atomic */ false,
+                        AccessType::NaRead,
                         access_range.size,
                         Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                     );
@@ -956,7 +1015,7 @@ impl VClockAlloc {
         &mut self,
         alloc_id: AllocId,
         access_range: AllocRange,
-        write_type: WriteType,
+        write_type: NaWriteType,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
         let current_span = machine.current_span();
@@ -978,8 +1037,7 @@ impl VClockAlloc {
                         global,
                         &machine.threads,
                         mem_clocks,
-                        write_type.get_descriptor(),
-                        /* is_atomic */ false,
+                        AccessType::NaWrite(write_type),
                         access_range.size,
                         Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                     );
@@ -1001,7 +1059,7 @@ impl VClockAlloc {
         range: AllocRange,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
-        self.unique_access(alloc_id, range, WriteType::Write, machine)
+        self.unique_access(alloc_id, range, NaWriteType::Write, machine)
     }
 
     /// Detect data-races for an unsynchronized deallocate operation, will not perform
@@ -1014,7 +1072,7 @@ impl VClockAlloc {
         range: AllocRange,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
-        self.unique_access(alloc_id, range, WriteType::Deallocate, machine)
+        self.unique_access(alloc_id, range, NaWriteType::Deallocate, machine)
     }
 }
 
@@ -1062,7 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     }
 
     /// Checks that an atomic access is legal at the given place.
-    fn atomic_access_check(&self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn atomic_access_check(
+        &self,
+        place: &MPlaceTy<'tcx, Provenance>,
+        access_type: AtomicAccessType,
+    ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
         // Check alignment requirements. Atomics must always be aligned to their size,
         // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must
@@ -1080,15 +1142,34 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
             .ptr_try_get_alloc_id(place.ptr())
             .expect("there are no zero-sized atomic accesses");
         if this.get_alloc_mutability(alloc_id)? == Mutability::Not {
-            // FIXME: make this prettier, once these messages have separate title/span/help messages.
-            throw_ub_format!(
-                "atomic operations cannot be performed on read-only memory\n\
-                many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails \
-                (and is hence nominally read-only)\n\
-                some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; \
-                it is possible that we could have an exception permitting this for specific kinds of loads\n\
-                please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you"
-            );
+            // See if this is fine.
+            match access_type {
+                AtomicAccessType::Rmw | AtomicAccessType::Store => {
+                    throw_ub_format!(
+                        "atomic store and read-modify-write operations cannot be performed on read-only memory\n\
+                        see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
+                    );
+                }
+                AtomicAccessType::Load(_)
+                    if place.layout.size > this.tcx.data_layout().pointer_size() =>
+                {
+                    throw_ub_format!(
+                        "large atomic load operations cannot be performed on read-only memory\n\
+                        these operations often have to be implemented using read-modify-write operations, which require writeable memory\n\
+                        see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
+                    );
+                }
+                AtomicAccessType::Load(o) if o != AtomicReadOrd::Relaxed => {
+                    throw_ub_format!(
+                        "non-relaxed atomic load operations cannot be performed on read-only memory\n\
+                        these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory\n\
+                        see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
+                    );
+                }
+                _ => {
+                    // Large relaxed loads are fine!
+                }
+            }
         }
         Ok(())
     }
@@ -1104,7 +1185,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         this.validate_atomic_op(
             place,
             atomic,
-            "Atomic Load",
+            AccessType::AtomicLoad,
             move |memory, clocks, index, atomic| {
                 if atomic == AtomicReadOrd::Relaxed {
                     memory.load_relaxed(&mut *clocks, index, place.layout.size)
@@ -1126,7 +1207,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         this.validate_atomic_op(
             place,
             atomic,
-            "Atomic Store",
+            AccessType::AtomicStore,
             move |memory, clocks, index, atomic| {
                 if atomic == AtomicWriteOrd::Relaxed {
                     memory.store_relaxed(clocks, index, place.layout.size)
@@ -1148,18 +1229,23 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         let acquire = matches!(atomic, Acquire | AcqRel | SeqCst);
         let release = matches!(atomic, Release | AcqRel | SeqCst);
         let this = self.eval_context_mut();
-        this.validate_atomic_op(place, atomic, "Atomic RMW", move |memory, clocks, index, _| {
-            if acquire {
-                memory.load_acquire(clocks, index, place.layout.size)?;
-            } else {
-                memory.load_relaxed(clocks, index, place.layout.size)?;
-            }
-            if release {
-                memory.rmw_release(clocks, index, place.layout.size)
-            } else {
-                memory.rmw_relaxed(clocks, index, place.layout.size)
-            }
-        })
+        this.validate_atomic_op(
+            place,
+            atomic,
+            AccessType::AtomicRmw,
+            move |memory, clocks, index, _| {
+                if acquire {
+                    memory.load_acquire(clocks, index, place.layout.size)?;
+                } else {
+                    memory.load_relaxed(clocks, index, place.layout.size)?;
+                }
+                if release {
+                    memory.rmw_release(clocks, index, place.layout.size)
+                } else {
+                    memory.rmw_relaxed(clocks, index, place.layout.size)
+                }
+            },
+        )
     }
 
     /// Generic atomic operation implementation
@@ -1167,7 +1253,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         &self,
         place: &MPlaceTy<'tcx, Provenance>,
         atomic: A,
-        description: &str,
+        access: AccessType,
         mut op: impl FnMut(
             &mut MemoryCellClocks,
             &mut ThreadClockSet,
@@ -1176,6 +1262,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         ) -> Result<(), DataRace>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
+        assert!(access.is_atomic());
         if let Some(data_race) = &this.machine.data_race {
             if data_race.race_detecting() {
                 let size = place.layout.size;
@@ -1185,7 +1272,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                 let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap();
                 log::trace!(
                     "Atomic op({}) with ordering {:?} on {:?} (size={})",
-                    description,
+                    access.description(),
                     &atomic,
                     place.ptr(),
                     size.bytes()
@@ -1207,8 +1294,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                                     data_race,
                                     &this.machine.threads,
                                     mem_clocks,
-                                    description,
-                                    /* is_atomic */ true,
+                                    access,
                                     place.layout.size,
                                     Pointer::new(
                                         alloc_id,
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 7bd5b4f2a92..fe445c6dcd9 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -4,7 +4,7 @@ use std::num::NonZeroU64;
 use log::trace;
 
 use rustc_errors::DiagnosticMessage;
-use rustc_span::{DUMMY_SP, SpanData, Symbol};
+use rustc_span::{SpanData, Symbol, DUMMY_SP};
 use rustc_target::abi::{Align, Size};
 
 use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory;
@@ -47,6 +47,7 @@ pub enum TerminationInfo {
         ptr: Pointer,
         op1: RacingOp,
         op2: RacingOp,
+        extra: Option<&'static str>,
     },
 }
 
@@ -75,7 +76,7 @@ impl fmt::Display for TerminationInfo {
                 write!(f, "multiple definitions of symbol `{link_name}`"),
             SymbolShimClashing { link_name, .. } =>
                 write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
-            DataRace { involves_non_atomic, ptr, op1, op2 } =>
+            DataRace { involves_non_atomic, ptr, op1, op2, .. } =>
                 write!(
                     f,
                     "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
@@ -266,12 +267,16 @@ pub fn report_error<'tcx, 'mir>(
                 vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
             Int2PtrWithStrictProvenance =>
                 vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
-            DataRace { op1, .. } =>
-                vec![
-                    (Some(op1.span), format!("and (1) occurred earlier here")),
-                    (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
-                    (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
-                ],
+            DataRace { op1, extra, .. } => {
+                let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))];
+                if let Some(extra) = extra {
+                    helps.push((None, format!("{extra}")))
+                }
+                helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")));
+                helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")));
+                helps
+            }
+                ,
             _ => vec![],
         };
         (title, helps)
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index a3193dfe20e..5b785c0143e 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -265,12 +265,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
 ) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>> {
     let param_env = ty::ParamEnv::reveal_all();
     let layout_cx = LayoutCx { tcx, param_env };
-    let mut ecx = InterpCx::new(
-        tcx,
-        rustc_span::DUMMY_SP,
-        param_env,
-        MiriMachine::new(config, layout_cx),
-    );
+    let mut ecx =
+        InterpCx::new(tcx, rustc_span::DUMMY_SP, param_env, MiriMachine::new(config, layout_cx));
 
     // Some parts of initialization require a full `InterpCx`.
     MiriMachine::late_init(&mut ecx, config, {
diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs
index e38b677f485..4d7f6a6b4e0 100644
--- a/src/tools/miri/src/shims/intrinsics/atomic.rs
+++ b/src/tools/miri/src/shims/intrinsics/atomic.rs
@@ -77,40 +77,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1)?, read_ord(ord2)?)?,
 
             ["or", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord)?)?,
             ["xor", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord)?)?,
             ["and", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord)?)?,
             ["nand", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord)?)?,
             ["xadd", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord)?)?,
             ["xsub", ord] =>
-                this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord)?)?,
+                this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord)?)?,
             ["min", ord] => {
                 // Later we will use the type to indicate signed vs unsigned,
                 // so make sure it matches the intrinsic name.
                 assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
-                this.atomic_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
+                this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
             }
             ["umin", ord] => {
                 // Later we will use the type to indicate signed vs unsigned,
                 // so make sure it matches the intrinsic name.
                 assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));
-                this.atomic_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
+                this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
             }
             ["max", ord] => {
                 // Later we will use the type to indicate signed vs unsigned,
                 // so make sure it matches the intrinsic name.
                 assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
-                this.atomic_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
+                this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
             }
             ["umax", ord] => {
                 // Later we will use the type to indicate signed vs unsigned,
                 // so make sure it matches the intrinsic name.
                 assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));
-                this.atomic_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
+                this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
             }
 
             _ => throw_unsup_format!("unimplemented intrinsic: `atomic_{intrinsic_name}`"),
@@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         Ok(())
     }
 
-    fn atomic_op(
+    fn atomic_rmw_op(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
@@ -213,7 +213,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                 Ok(())
             }
             AtomicOp::MirOp(op, neg) => {
-                let old = this.atomic_op_immediate(&place, &rhs, op, neg, atomic)?;
+                let old = this.atomic_rmw_op_immediate(&place, &rhs, op, neg, atomic)?;
                 this.write_immediate(*old, dest)?; // old value is returned
                 Ok(())
             }
diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs
index 868b3beb53b..7c67ea45bdf 100644
--- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs
+++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.rs
@@ -17,7 +17,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: /Data race detected between \(1\) (Read|Write) on thread `<unnamed>` and \(2\) Write on thread `<unnamed>`/
+        *p = 5; //~ ERROR: /Data race detected between \(1\) non-atomic (read|write) on thread `<unnamed>` and \(2\) non-atomic write on thread `<unnamed>`/
     }
 }
 
diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr
index da5af600675..0de2f66fe0b 100644
--- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |         ^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/retag_data_race_write.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr
index 37d216b9877..8036c974eec 100644
--- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |         ^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/retag_data_race_write.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.rs b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.rs
index cb6aeea665d..88c73d14ef7 100644
--- a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.rs
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.rs
@@ -7,5 +7,5 @@ fn main() {
     static X: i32 = 0;
     let x = &X as *const i32 as *const AtomicI32;
     let x = unsafe { &*x };
-    x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); //~ERROR: atomic operations cannot be performed on read-only memory
+    x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); //~ERROR: cannot be performed on read-only memory
 }
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr
index d51fdee0b25..fc5982e7f94 100644
--- a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr
@@ -1,14 +1,10 @@
-error: Undefined Behavior: atomic operations cannot be performed on read-only memory
-       many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
-       some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
-       please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
+error: Undefined Behavior: atomic store and read-modify-write operations cannot be performed on read-only memory
+       see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
   --> $DIR/read_only_atomic_cmpxchg.rs:LL:CC
    |
 LL |     x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory
-many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
-some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
-please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ atomic store and read-modify-write operations cannot be performed on read-only memory
+see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load.stderr b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load.stderr
deleted file mode 100644
index 17851d6b470..00000000000
--- a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error: Undefined Behavior: atomic operations cannot be performed on read-only memory
-       many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
-       some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
-       please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
-  --> $DIR/read_only_atomic_load.rs:LL:CC
-   |
-LL |     x.load(Ordering::Relaxed);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory
-many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
-some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
-please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
-   |
-   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
-   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/read_only_atomic_load.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load.rs b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.rs
index 6e92453e3c1..af0dc2d3fd6 100644
--- a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load.rs
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.rs
@@ -9,5 +9,5 @@ fn main() {
     let x = unsafe { &*x };
     // Some targets can implement atomic loads via compare_exchange, so we cannot allow them on
     // read-only memory.
-    x.load(Ordering::Relaxed); //~ERROR: atomic operations cannot be performed on read-only memory
+    x.load(Ordering::Acquire); //~ERROR: cannot be performed on read-only memory
 }
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.stderr b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.stderr
new file mode 100644
index 00000000000..2945344877a
--- /dev/null
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_acquire.stderr
@@ -0,0 +1,19 @@
+error: Undefined Behavior: non-relaxed atomic load operations cannot be performed on read-only memory
+       these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory
+       see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
+  --> $DIR/read_only_atomic_load_acquire.rs:LL:CC
+   |
+LL |     x.load(Ordering::Acquire);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ non-relaxed atomic load operations cannot be performed on read-only memory
+these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory
+see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/read_only_atomic_load_acquire.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.rs b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.rs
new file mode 100644
index 00000000000..a9a8f0f5ddd
--- /dev/null
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.rs
@@ -0,0 +1,18 @@
+// Should not rely on the aliasing model for its failure.
+//@compile-flags: -Zmiri-disable-stacked-borrows
+// Needs atomic accesses larger than the pointer size
+//@ignore-64bit
+
+use std::sync::atomic::{AtomicI64, Ordering};
+
+#[repr(align(8))]
+struct AlignedI64(i64);
+
+fn main() {
+    static X: AlignedI64 = AlignedI64(0);
+    let x = &X as *const AlignedI64 as *const AtomicI64;
+    let x = unsafe { &*x };
+    // Some targets can implement atomic loads via compare_exchange, so we cannot allow them on
+    // read-only memory.
+    x.load(Ordering::Relaxed); //~ERROR: cannot be performed on read-only memory
+}
diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.stderr b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.stderr
new file mode 100644
index 00000000000..5d8cb707f3f
--- /dev/null
+++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_load_large.stderr
@@ -0,0 +1,19 @@
+error: Undefined Behavior: large atomic load operations cannot be performed on read-only memory
+       these operations often have to be implemented using read-modify-write operations, which require writeable memory
+       see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
+  --> $DIR/read_only_atomic_load_large.rs:LL:CC
+   |
+LL |     x.load(Ordering::Relaxed);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ large atomic load operations cannot be performed on read-only memory
+these operations often have to be implemented using read-modify-write operations, which require writeable memory
+see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/read_only_atomic_load_large.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_match_never.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_match_never.rs
index 723c3f1e158..e77c8e06a0f 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_match_never.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_match_never.rs
@@ -14,4 +14,3 @@ fn main() {
     }
     panic!("this should never print");
 }
-
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.rs
index 22a5ce8ea74..22a5ce8ea74 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.rs
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.stderr
index 20f3a25a0b1..16841626dc2 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
-  --> $DIR/dangling_pointer_project_underscore.rs:LL:CC
+  --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
    |
 LL |         let _ = (*p).1;
    |                 ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
@@ -7,17 +7,17 @@ LL |         let _ = (*p).1;
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
 help: ALLOC was allocated here:
-  --> $DIR/dangling_pointer_project_underscore.rs:LL:CC
+  --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
    |
 LL |         let b = Box::new(42);
    |                 ^^^^^^^^^^^^
 help: ALLOC was deallocated here:
-  --> $DIR/dangling_pointer_project_underscore.rs:LL:CC
+  --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
    |
 LL |     };
    |     ^
    = note: BACKTRACE (of the first span):
-   = note: inside `main` at $DIR/dangling_pointer_project_underscore.rs:LL:CC
+   = note: inside `main` at $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.rs
new file mode 100644
index 00000000000..fc10a826c1e
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.rs
@@ -0,0 +1,12 @@
+// Make sure we find these even with many checks disabled.
+//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
+
+fn main() {
+    let p = {
+        let b = Box::new(42);
+        &*b as *const i32 as *const (u8, u8, u8, u8)
+    };
+    unsafe {
+        let _: u8 = (*p).1; //~ ERROR: out-of-bounds pointer arithmetic
+    }
+}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.stderr
new file mode 100644
index 00000000000..0cdb6639a2f
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_let_type_annotation.stderr
@@ -0,0 +1,25 @@
+error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
+  --> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
+   |
+LL |         let _: u8 = (*p).1;
+   |                     ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/pass/dangling_pointer_deref_match_underscore.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.rs
index c3cff1f4280..8541da84857 100644
--- a/src/tools/miri/tests/pass/dangling_pointer_deref_match_underscore.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.rs
@@ -1,13 +1,14 @@
-// A `_` binding in a match is a nop, so we do not detect that the pointer is dangling.
+// Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
 
 fn main() {
     let p = {
         let b = Box::new(42);
-        &*b as *const i32
+        &*b as *const i32 as *const (u8, u8, u8, u8)
     };
     unsafe {
-        match *p {
+        match (*p).1 {
+            //~^ ERROR: out-of-bounds pointer arithmetic
             _ => {}
         }
     }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.stderr
new file mode 100644
index 00000000000..625a7b5f60b
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore_match.stderr
@@ -0,0 +1,25 @@
+error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
+  --> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
+   |
+LL |         match (*p).1 {
+   |               ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
index 42077dfae2d..786e57666e2 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
@@ -39,7 +39,7 @@ pub fn main() {
             let pointer = &*ptr.0;
 
             // Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
-            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
index 5b809722c70..9d21a3e0a45 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_read_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/alloc_read_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
index 53f4e637a19..8c685dcb760 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
@@ -37,7 +37,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
-            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
index 8520bcf4e4e..13a19109e88 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_write_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed) = 2;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/alloc_write_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
index 9606df1d6ff..d7e9561caf3 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
@@ -22,7 +22,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
+            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic load on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
index e25629e14ea..f55f839d0b8 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).load(Ordering::SeqCst)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_read_na_write_race1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
index 0e29ab32eef..62bf8b65561 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
@@ -25,7 +25,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
index 6953b1403b4..a20c220b6c2 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_read_na_write_race2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
index 6f1792bc8f4..9186c562670 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
@@ -25,7 +25,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+            *atomic_ref.get_mut() //~ ERROR: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
index e52b8895a6a..a91d4cee054 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race1.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut()
-   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_write_na_read_race1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
index e84207e655d..0fcae906f09 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
@@ -22,7 +22,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
+            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
index 513d13b0349..8831d9cfc1c 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race2.rs:LL:CC
    |
 LL |             (&*c.0).store(32, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_write_na_read_race2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
index ca269b1bd2a..822d86c1c1d 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
@@ -22,7 +22,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
+            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
index 2ff70ef1f6d..5aed907b166 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).store(64, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_write_na_write_race1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
index 0d69a9a332d..d84531646e2 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
@@ -25,7 +25,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
index 166b4d2269a..65114296f52 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/atomic_write_na_write_race2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
index 0679b81f012..0fdb8e631a1 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
@@ -36,7 +36,7 @@ fn main() {
     let join2 = unsafe {
         spawn(move || {
             let c = c; // capture `c`, not just its field.
-            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         })
     };
 
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
index a08b21ab0e4..7ac3a9cc929 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_async_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dangling_thread_async_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
index 3c5dd424eb1..fa2176d844f 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
@@ -34,6 +34,6 @@ fn main() {
     spawn(|| ()).join().unwrap();
 
     unsafe {
-        *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
+        *c.0 = 64; //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main`
     }
 }
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
index aa2e6a6f712..49256dff51f 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_race.rs:LL:CC
    |
 LL |         *c.0 = 64;
-   |         ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
+   |         ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dangling_thread_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
index 3c25cdc0d8d..1d914f0a808 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
@@ -27,7 +27,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let ptr = ptr; // avoid field capturing
             __rust_dealloc(
-                //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
index 5e546646479..ef6b0c3616b 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,7 +7,7 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+   | |_____________^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dealloc_read_race1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
index c921ce6b716..53f1d19fa71 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
@@ -30,7 +30,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let ptr = ptr; // avoid field capturing
-            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) deallocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 //~ ERROR: has been freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
index 87b5f204816..728dc64d828 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
@@ -36,7 +36,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
index beb70c5a7fa..805d7c19642 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dealloc_read_race_stack.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
index b700f50ce19..e0d7f983a63 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
@@ -26,7 +26,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let ptr = ptr; // avoid field capturing
             __rust_dealloc(
-                //~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
index cc4c4524ba2..22ef35959f2 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,7 +7,7 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+   | |_____________^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dealloc_write_race1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
index e01132202d4..11b9d97527c 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
@@ -29,7 +29,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let ptr = ptr; // avoid field capturing
-            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) deallocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 = 2; //~ ERROR: has been freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
index 3d35187a018..da3cdc23ad6 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
@@ -36,7 +36,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
index 5f9f4f9bee4..52c9abd5fe0 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/dealloc_write_race_stack.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
index b44be4ac64e..c1407fc5391 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
@@ -32,7 +32,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
index 84d1c0bf7e6..1d8bf2d0d26 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/enable_after_join_to_main.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/enable_after_join_to_main.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.rs b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
index 0648aa55f4a..12c74740387 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.rs
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
@@ -20,5 +20,5 @@ fn main() {
     // The fence is useless, since it did not happen-after the `store` in the other thread.
     // Hence this is a data race.
     // Also see https://github.com/rust-lang/miri/issues/2192.
-    unsafe { V = 2 } //~ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
+    unsafe { V = 2 } //~ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main`
 }
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
index c30d2354e76..17bcf24a505 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/fence_after_load.rs:LL:CC
    |
 LL |     unsafe { V = 2 }
-   |              ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
+   |              ^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/fence_after_load.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read.rs b/src/tools/miri/tests/fail/data_race/mixed_size_read.rs
index d530ed2f5a4..871d5f9a9db 100644
--- a/src/tools/miri/tests/fail/data_race/mixed_size_read.rs
+++ b/src/tools/miri/tests/fail/data_race/mixed_size_read.rs
@@ -19,7 +19,7 @@ fn main() {
         });
         s.spawn(|| {
             a8[0].load(Ordering::SeqCst);
-            //~^ ERROR: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>`
+            //~^ ERROR: Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>`
         });
     });
 }
diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr
index 06944a11db8..cb7dc89359a 100644
--- a/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr
+++ b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/mixed_size_read.rs:LL:CC
    |
 LL |             a8[0].load(Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/mixed_size_read.rs:LL:CC
    |
 LL |             a16.load(Ordering::SeqCst);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: overlapping unsynchronized atomic accesses must use the same access size
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_write.rs b/src/tools/miri/tests/fail/data_race/mixed_size_write.rs
index df3551612c3..e52e76e4802 100644
--- a/src/tools/miri/tests/fail/data_race/mixed_size_write.rs
+++ b/src/tools/miri/tests/fail/data_race/mixed_size_write.rs
@@ -19,7 +19,7 @@ fn main() {
         });
         s.spawn(|| {
             a8[0].store(1, Ordering::SeqCst);
-            //~^ ERROR: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>`
+            //~^ ERROR: Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>`
         });
     });
 }
diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr
index 4bb949175bf..b3908e9c6bf 100644
--- a/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr
+++ b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/mixed_size_write.rs:LL:CC
    |
 LL |             a8[0].store(1, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/mixed_size_write.rs:LL:CC
    |
 LL |             a16.store(1, Ordering::SeqCst);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: overlapping unsynchronized atomic accesses must use the same access size
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/fail/data_race/read_read_race1.rs b/src/tools/miri/tests/fail/data_race/read_read_race1.rs
index eebfbc74d40..dd800af4af7 100644
--- a/src/tools/miri/tests/fail/data_race/read_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/read_read_race1.rs
@@ -21,7 +21,7 @@ fn main() {
             unsafe { ptr.read() };
             // Then do the atomic access.
             a.load(Ordering::SeqCst);
-            //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
+            //~^ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>`
         });
     });
 }
diff --git a/src/tools/miri/tests/fail/data_race/read_read_race1.stderr b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr
index 158b438bd0d..0846a88f362 100644
--- a/src/tools/miri/tests/fail/data_race/read_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_read_race1.rs:LL:CC
    |
 LL |             a.load(Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/read_read_race1.rs:LL:CC
    |
 LL |             unsafe { ptr.read() };
    |                      ^^^^^^^^^^
+   = help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/fail/data_race/read_read_race2.rs b/src/tools/miri/tests/fail/data_race/read_read_race2.rs
index 230b429e287..1f35cb639c3 100644
--- a/src/tools/miri/tests/fail/data_race/read_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/read_read_race2.rs
@@ -21,7 +21,7 @@ fn main() {
 
             let ptr = &a as *const AtomicU16 as *mut u16;
             unsafe { ptr.read() };
-            //~^ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+            //~^ ERROR: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
         });
     });
 }
diff --git a/src/tools/miri/tests/fail/data_race/read_read_race2.stderr b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr
index 7f867b9edbb..c6181cc45b2 100644
--- a/src/tools/miri/tests/fail/data_race/read_read_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_read_race2.rs:LL:CC
    |
 LL |             unsafe { ptr.read() };
-   |                      ^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                      ^^^^^^^^^^ Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/read_read_race2.rs:LL:CC
    |
 LL |             a.load(Ordering::SeqCst);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.rs b/src/tools/miri/tests/fail/data_race/read_write_race.rs
index aed3ca767f6..37208549686 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.rs
@@ -21,7 +21,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            *c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.stderr b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
index 13bc5c74ae3..c3fdcdf9308 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/read_write_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
index c3e5c401d87..df000b7942e 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
@@ -40,7 +40,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+            stack_var //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
index 96fcb494822..1e45878bfdd 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race_stack.rs:LL:CC
    |
 LL |             stack_var
-   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/read_write_race_stack.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
index 1b691b996f1..f20dcec4e28 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
@@ -39,7 +39,7 @@ pub fn main() {
         let j3 = spawn(move || {
             let c = c; // avoid field capturing
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
index 92755f5551d..0c574299b69 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/relax_acquire_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                 ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/relax_acquire_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.rs b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
index 80b30053fc7..4050895f296 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
@@ -43,7 +43,7 @@ pub fn main() {
             let c = c; // avoid field capturing
             sleep(Duration::from_millis(500));
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
index 880268730db..9aff6c6c3a7 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                 ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/release_seq_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
index 33de1f17558..2cba38a8e1e 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
@@ -39,7 +39,7 @@ pub fn main() {
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
index 386c012ba4e..f0522404fde 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race_same_thread.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                 ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/release_seq_race_same_thread.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.rs b/src/tools/miri/tests/fail/data_race/rmw_race.rs
index 4d0ce8f9433..973ebdf48d3 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.rs
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.rs
@@ -40,7 +40,7 @@ pub fn main() {
         let j3 = spawn(move || {
             let c = c; // capture `c`, not just its field.
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.stderr b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
index 82cb2c4ecbb..b400b2b9a17 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/rmw_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                 ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/rmw_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
index d3c2ab3e4a4..047d3757f14 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
@@ -21,4 +21,4 @@ fn race(local: i32) {
     // Deallocating the local (when `main` returns)
     // races with the read in the other thread.
     // Make sure the error points at this function's end, not just the call site.
-} //~ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main`
+} //~ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `main`
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
index 71e38c2727e..e6804f6520c 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
   --> $DIR/stack_pop_race.rs:LL:CC
    |
 LL | }
-   |  ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
+   |  ^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/stack_pop_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.rs b/src/tools/miri/tests/fail/data_race/write_write_race.rs
index 30e3460f222..05ec8d63c7a 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.rs
@@ -21,7 +21,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let c = c; // avoid field capturing
-            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.stderr b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
index 3b7eb2b8000..bc793e9afb0 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/write_write_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
index 25be42bd4eb..d3ef552eab8 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
@@ -40,7 +40,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var = 1usize; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+            stack_var = 1usize; //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
 
             // read to silence errors
             stack_var
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
index c501ecd11a6..ea62dbf96b9 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race_stack.rs:LL:CC
    |
 LL |             stack_var = 1usize;
-   |             ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/write_write_race_stack.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs
index 670fe9858ed..71f1f132bc7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs
@@ -13,7 +13,7 @@ fn main() {
         let ptr = ptr;
         // We do a protected mutable retag (but no write!) in this thread.
         fn retag(_x: &mut i32) {}
-        retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>`
+        retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>`
     });
 
     // We do a read in the main thread.
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr
index 10fb1dece2a..ce77976f88b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_protected_read.rs:LL:CC
    |
 LL |         retag(unsafe { &mut *ptr.0 });
-   |                        ^^^^^^^^^^^ Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |                        ^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/retag_data_race_protected_read.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
index 0637e08af9b..46694cd49e3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
@@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+        *p = 5; //~ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
index c53a495b5e1..1496c353e52 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_read.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |         ^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/retag_data_race_read.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/union-uninhabited-match-underscore.rs b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.rs
index 33db9c2d347..6c1df45ac0e 100644
--- a/src/tools/miri/tests/pass/union-uninhabited-match-underscore.rs
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.rs
@@ -8,10 +8,8 @@ fn main() {
     unsafe {
         let x: Uninit<Void> = Uninit { uninit: () };
         match x.value {
-            // rustc warns about un unreachable pattern,
-            // but is wrong in unsafe code.
             #[allow(unreachable_patterns)]
-            _ => println!("hi from the void!"),
+            _x => println!("hi from the void!"), //~ERROR: invalid value
         }
     }
 }
diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr
new file mode 100644
index 00000000000..c234467bddc
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a value of uninhabited type `main::Void`
+  --> $DIR/match_binder_checks_validity1.rs:LL:CC
+   |
+LL |             _x => println!("hi from the void!"),
+   |             ^^ constructing invalid value: encountered a value of uninhabited type `main::Void`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/match_binder_checks_validity1.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.rs b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.rs
new file mode 100644
index 00000000000..0517263a8f5
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.rs
@@ -0,0 +1,14 @@
+fn main() {
+    #[derive(Copy, Clone)]
+    union Uninit<T: Copy> {
+        value: T,
+        uninit: u8,
+    }
+    unsafe {
+        let x: Uninit<bool> = Uninit { uninit: 3 };
+        match x.value {
+            #[allow(unreachable_patterns)]
+            _x => println!("hi from the void!"), //~ERROR: invalid value
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr
new file mode 100644
index 00000000000..8af2d37d74a
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered 0x03, but expected a boolean
+  --> $DIR/match_binder_checks_validity2.rs:LL:CC
+   |
+LL |             _x => println!("hi from the void!"),
+   |             ^^ constructing invalid value: encountered 0x03, but expected a boolean
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/match_binder_checks_validity2.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs
index 36dc0d5f3f7..e36d947565a 100644
--- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs
+++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs
@@ -31,7 +31,7 @@ pub fn main() {
         let x_split = split_u32_ptr(x_ptr);
         unsafe {
             let hi = ptr::addr_of!((*x_split)[0]);
-            std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: different-size
+            std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load
         }
     });
 
diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr
index 055585ab96f..03b5a4e4c17 100644
--- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr
+++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Race condition detected between (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/racing_mixed_size.rs:LL:CC
    |
 LL |             std::intrinsics::atomic_load_relaxed(hi);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/racing_mixed_size.rs:LL:CC
    |
 LL |         x.store(1, Relaxed);
    |         ^^^^^^^^^^^^^^^^^^^
+   = help: overlapping unsynchronized atomic accesses must use the same access size
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs
index 5cd14540ca3..34917245ea5 100644
--- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs
+++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs
@@ -29,7 +29,7 @@ pub fn main() {
         let x_split = split_u32_ptr(x_ptr);
         unsafe {
             let hi = x_split as *const u16 as *const AtomicU16;
-            (*hi).load(Relaxed); //~ ERROR: different-size
+            (*hi).load(Relaxed); //~ ERROR: (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load
         }
     });
 
diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr
index 2eefa0a87b4..05eba41f4d5 100644
--- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr
+++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr
@@ -1,14 +1,15 @@
-error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+error: Undefined Behavior: Race condition detected between (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/racing_mixed_size_read.rs:LL:CC
    |
 LL |             (*hi).load(Relaxed);
-   |             ^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
+   |             ^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> $DIR/racing_mixed_size_read.rs:LL:CC
    |
 LL |         x.load(Relaxed);
    |         ^^^^^^^^^^^^^^^
+   = help: overlapping unsynchronized atomic accesses must use the same access size
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
diff --git a/src/tools/miri/tests/pass/atomic-readonly-load.rs b/src/tools/miri/tests/pass/atomic-readonly-load.rs
new file mode 100644
index 00000000000..8f8086b3538
--- /dev/null
+++ b/src/tools/miri/tests/pass/atomic-readonly-load.rs
@@ -0,0 +1,12 @@
+// Stacked Borrows doesn't like this.
+//@compile-flags: -Zmiri-tree-borrows
+
+use std::sync::atomic::*;
+
+fn main() {
+    // Atomic loads from read-only memory are fine if they are relaxed and small.
+    static X: i32 = 0;
+    let x = &X as *const i32 as *const AtomicI32;
+    let x = unsafe { &*x };
+    x.load(Ordering::Relaxed);
+}
diff --git a/src/tools/miri/tests/pass/underscore_pattern.rs b/src/tools/miri/tests/pass/underscore_pattern.rs
new file mode 100644
index 00000000000..b0e85bc1bb0
--- /dev/null
+++ b/src/tools/miri/tests/pass/underscore_pattern.rs
@@ -0,0 +1,71 @@
+// Various tests ensuring that underscore patterns really just construct the place, but don't check its contents.
+#![feature(strict_provenance)]
+use std::ptr;
+
+fn main() {
+    dangling_match();
+    invalid_match();
+    dangling_let();
+    invalid_let();
+    dangling_let_type_annotation();
+    invalid_let_type_annotation();
+}
+
+fn dangling_match() {
+    let p = {
+        let b = Box::new(42);
+        &*b as *const i32
+    };
+    unsafe {
+        match *p {
+            _ => {}
+        }
+    }
+}
+
+fn invalid_match() {
+    union Uninit<T: Copy> {
+        value: T,
+        uninit: (),
+    }
+    unsafe {
+        let x: Uninit<bool> = Uninit { uninit: () };
+        match x.value {
+            _ => {}
+        }
+    }
+}
+
+fn dangling_let() {
+    unsafe {
+        let ptr = ptr::invalid::<bool>(0x40);
+        let _ = *ptr;
+    }
+}
+
+fn invalid_let() {
+    unsafe {
+        let val = 3u8;
+        let ptr = ptr::addr_of!(val).cast::<bool>();
+        let _ = *ptr;
+    }
+}
+
+// Adding a type annotation used to change how MIR is generated, make sure we cover both cases.
+fn dangling_let_type_annotation() {
+    unsafe {
+        let ptr = ptr::invalid::<bool>(0x40);
+        let _: bool = *ptr;
+    }
+}
+
+fn invalid_let_type_annotation() {
+    unsafe {
+        let val = 3u8;
+        let ptr = ptr::addr_of!(val).cast::<bool>();
+        let _: bool = *ptr;
+    }
+}
+
+// FIXME: we should also test `!`, not just `bool` -- but that s currently buggy:
+// https://github.com/rust-lang/rust/issues/117288
diff --git a/src/tools/miri/tests/pass/union-uninhabited-match-underscore.stdout b/src/tools/miri/tests/pass/union-uninhabited-match-underscore.stdout
deleted file mode 100644
index ff731696f01..00000000000
--- a/src/tools/miri/tests/pass/union-uninhabited-match-underscore.stdout
+++ /dev/null
@@ -1 +0,0 @@
-hi from the void!
diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml
index 471f2b5ac73..cdd867c5f15 100644
--- a/src/tools/rust-installer/Cargo.toml
+++ b/src/tools/rust-installer/Cargo.toml
@@ -16,7 +16,6 @@ rayon = "1.0"
 tar = "0.4.38"
 walkdir = "2"
 xz2 = "0.1.4"
-num_cpus = "1"
 
 [dependencies.clap]
 features = ["derive"]
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 16b8ce7a916..8a4089a56f0 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -264,7 +264,7 @@ fn rewrite_closure_fn_decl(
         ""
     };
     let is_async = if asyncness.is_async() { "async " } else { "" };
-    let mover = if capture == ast::CaptureBy::Value {
+    let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
         "move "
     } else {
         ""
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 8c2262fde81..fa941e6146a 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -368,7 +368,7 @@ pub(crate) fn format_expr(
             }
         }
         ast::ExprKind::Gen(capture_by, ref block, ref kind) => {
-            let mover = if capture_by == ast::CaptureBy::Value {
+            let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
                 "move "
             } else {
                 ""
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 4b12e9172af..7ad75f089f3 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -31,12 +31,49 @@ const LICENSES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
+type ExceptionList = &'static [(&'static str, &'static str)];
+
+/// The workspaces to check for licensing and optionally permitted dependencies.
+///
+/// Each entry consists of a tuple with the following elements:
+///
+/// * The path to the workspace root Cargo.toml file.
+/// * The list of license exceptions.
+/// * Optionally a tuple of:
+///     * A list of crates for which dependencies need to be explicitly allowed.
+///     * The list of allowed dependencies.
+// FIXME auto detect all cargo workspaces
+pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)] = &[
+    // The root workspace has to be first for check_rustfix to work.
+    (".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES))),
+    // Outside of the alphabetical section because rustfmt formats it using multiple lines.
+    (
+        "compiler/rustc_codegen_cranelift",
+        EXCEPTIONS_CRANELIFT,
+        Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
+    ),
+    // tidy-alphabetical-start
+    //("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None), // FIXME uncomment once all deps are vendored
+    //("library/backtrace", &[], None), // FIXME uncomment once rust-lang/backtrace#562 has been synced back to the rust repo
+    //("library/portable-simd", &[], None), // FIXME uncomment once rust-lang/portable-simd#363 has been synced back to the rust repo
+    //("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo
+    ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None),
+    ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None),
+    //("src/etc/test-float-parse", &[], None), // FIXME uncomment once all deps are vendored
+    ("src/tools/cargo", EXCEPTIONS_CARGO, None),
+    //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
+    //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
+    ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
+    ("src/tools/x", &[], None),
+    // tidy-alphabetical-end
+];
+
 /// These are exceptions to Rust's permissive licensing policy, and
 /// should be considered bugs. Exceptions are only allowed in Rust
 /// tooling. It is _crucial_ that no exception crates be dependencies
 /// of the Rust runtime (std/test).
 #[rustfmt::skip]
-const EXCEPTIONS: &[(&str, &str)] = &[
+const EXCEPTIONS: ExceptionList = &[
     // tidy-alphabetical-start
     ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc
     ("colored", "MPL-2.0"),                                  // rustfmt
@@ -49,17 +86,27 @@ const EXCEPTIONS: &[(&str, &str)] = &[
     ("openssl", "Apache-2.0"),                               // opt-dist
     ("option-ext", "MPL-2.0"),                               // cargo-miri (via `directories`)
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),     // rustc (license is the same as LLVM uses)
-    ("ryu", "Apache-2.0 OR BSL-1.0"),                        // cargo/... (because of serde)
+    ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0                       // cargo/... (because of serde)
     ("self_cell", "Apache-2.0"),                             // rustc (fluent translations)
     ("snap", "BSD-3-Clause"),                                // rustc
     // tidy-alphabetical-end
 ];
 
-const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
+// FIXME uncomment once rust-lang/stdarch#1462 lands
+/*
+const EXCEPTIONS_STDARCH: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
+    ("wasmparser", "Apache-2.0 WITH LLVM-exception"),
+    ("wasmprinter", "Apache-2.0 WITH LLVM-exception"),
+    // tidy-alphabetical-end
+];
+*/
+
+const EXCEPTIONS_CARGO: ExceptionList = &[
     // tidy-alphabetical-start
     ("bitmaps", "MPL-2.0+"),
     ("bytesize", "Apache-2.0"),
-    ("byteyarn", "Apache-2.0"),
     ("ciborium", "Apache-2.0"),
     ("ciborium-io", "Apache-2.0"),
     ("ciborium-ll", "Apache-2.0"),
@@ -69,7 +116,7 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
     ("im-rc", "MPL-2.0+"),
     ("normalize-line-endings", "Apache-2.0"),
     ("openssl", "Apache-2.0"),
-    ("ryu", "Apache-2.0 OR BSL-1.0"),
+    ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
     ("sha1_smol", "BSD-3-Clause"),
     ("similar", "Apache-2.0"),
     ("sized-chunks", "MPL-2.0+"),
@@ -78,7 +125,20 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
     // tidy-alphabetical-end
 ];
 
-const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
+const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("anymap", "BlueOak-1.0.0 OR MIT OR Apache-2.0"), // BlueOak is not acceptable, but we use it under MIT OR Apache-2 .0
+    ("dissimilar", "Apache-2.0"),
+    ("instant", "BSD-3-Clause"),
+    ("notify", "CC0-1.0"),
+    ("pulldown-cmark-to-cmark", "Apache-2.0"),
+    ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
+    ("scip", "Apache-2.0"),
+    ("snap", "BSD-3-Clause"),
+    // tidy-alphabetical-end
+];
+
+const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-start
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
@@ -99,8 +159,22 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
     // tidy-alphabetical-end
 ];
 
-const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
-    ("ryu", "Apache-2.0 OR BSL-1.0"), // through serde
+// FIXME uncomment once all deps are vendored
+/*
+const EXCEPTIONS_GCC: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("gccjit", "GPL-3.0"),
+    ("gccjit_sys", "GPL-3.0"),
+    // tidy-alphabetical-end
+];
+*/
+
+const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[
+    ("ryu", "Apache-2.0 OR BSL-1.0"), // through serde. BSL is not acceptble, but we use it under Apache-2.0
+];
+
+const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
+    ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptible, but we use it under MIT OR Apache-2.0
 ];
 
 /// These are the root crates that are part of the runtime. The licenses for
@@ -154,7 +228,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "ena",
     "equivalent",
     "errno",
-    "errno-dragonfly",
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
@@ -185,6 +258,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "is-terminal",
     "itertools",
     "itoa",
+    "jemalloc-sys",
     "jobserver",
     "lazy_static",
     "libc",
@@ -212,6 +286,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "perf-event-open-sys",
     "pin-project-lite",
     "polonius-engine",
+    "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std
     "ppv-lite86",
     "proc-macro-hack",
     "proc-macro2",
@@ -383,65 +458,90 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
 /// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path
 /// to the cargo executable.
 pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
-    let mut cmd = cargo_metadata::MetadataCommand::new();
-    cmd.cargo_path(cargo)
-        .manifest_path(root.join("Cargo.toml"))
-        .features(cargo_metadata::CargoOpt::AllFeatures);
-    let metadata = t!(cmd.exec());
-    let runtime_ids = compute_runtime_crates(&metadata);
-    check_license_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
-    check_permitted_dependencies(
-        &metadata,
-        "rustc",
-        PERMITTED_RUSTC_DEPENDENCIES,
-        &["rustc_driver", "rustc_codegen_llvm"],
-        bad,
-    );
-
-    // Check cargo independently as it has it's own workspace.
-    let mut cmd = cargo_metadata::MetadataCommand::new();
-    cmd.cargo_path(cargo)
-        .manifest_path(root.join("src/tools/cargo/Cargo.toml"))
-        .features(cargo_metadata::CargoOpt::AllFeatures);
-    let cargo_metadata = t!(cmd.exec());
-    let runtime_ids = HashSet::new();
-    check_license_exceptions(&cargo_metadata, EXCEPTIONS_CARGO, runtime_ids, bad);
-    check_rustfix(&metadata, &cargo_metadata, bad);
-
-    // Check rustc_codegen_cranelift independently as it has it's own workspace.
-    let mut cmd = cargo_metadata::MetadataCommand::new();
-    cmd.cargo_path(cargo)
-        .manifest_path(root.join("compiler/rustc_codegen_cranelift/Cargo.toml"))
-        .features(cargo_metadata::CargoOpt::AllFeatures);
-    let metadata = t!(cmd.exec());
-    let runtime_ids = HashSet::new();
-    check_license_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
-    check_permitted_dependencies(
-        &metadata,
-        "cranelift",
-        PERMITTED_CRANELIFT_DEPENDENCIES,
-        &["rustc_codegen_cranelift"],
-        bad,
-    );
-
-    let mut cmd = cargo_metadata::MetadataCommand::new();
-    cmd.cargo_path(cargo)
-        .manifest_path(root.join("src/bootstrap/Cargo.toml"))
-        .features(cargo_metadata::CargoOpt::AllFeatures);
-    let metadata = t!(cmd.exec());
-    let runtime_ids = HashSet::new();
-    check_license_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
+    let mut checked_runtime_licenses = false;
+    let mut rust_metadata = None;
+
+    for &(workspace, exceptions, permitted_deps) in WORKSPACES {
+        if !root.join(workspace).join("Cargo.lock").exists() {
+            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
+            continue;
+        }
+
+        let mut cmd = cargo_metadata::MetadataCommand::new();
+        cmd.cargo_path(cargo)
+            .manifest_path(root.join(workspace).join("Cargo.toml"))
+            .features(cargo_metadata::CargoOpt::AllFeatures)
+            .other_options(vec!["--locked".to_owned()]);
+        let metadata = t!(cmd.exec());
+
+        check_license_exceptions(&metadata, exceptions, bad);
+        if let Some((crates, permitted_deps)) = permitted_deps {
+            check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad);
+        }
+
+        if workspace == "." {
+            let runtime_ids = compute_runtime_crates(&metadata);
+            check_runtime_license_exceptions(&metadata, runtime_ids, bad);
+            checked_runtime_licenses = true;
+            rust_metadata = Some(metadata);
+        } else if workspace == "src/tools/cargo" {
+            check_rustfix(
+                rust_metadata
+                    .as_ref()
+                    .expect("The root workspace should be the first to be checked"),
+                &metadata,
+                bad,
+            );
+        }
+    }
+
+    // Sanity check to ensure we don't accidentally remove the workspace containing the runtime
+    // crates.
+    assert!(checked_runtime_licenses);
 }
 
-/// Check that all licenses are in the valid list in `LICENSES`.
+/// Check that all licenses of runtime dependencies are in the valid list in `LICENSES`.
 ///
-/// Packages listed in `exceptions` are allowed for tools.
-fn check_license_exceptions(
+/// Unlike for tools we don't allow exceptions to the `LICENSES` list for the runtime with the sole
+/// exception of `fortanix-sgx-abi` which is only used on x86_64-fortanix-unknown-sgx.
+fn check_runtime_license_exceptions(
     metadata: &Metadata,
-    exceptions: &[(&str, &str)],
     runtime_ids: HashSet<&PackageId>,
     bad: &mut bool,
 ) {
+    for pkg in &metadata.packages {
+        if !runtime_ids.contains(&pkg.id) {
+            // Only checking dependencies of runtime libraries here.
+            continue;
+        }
+        if pkg.source.is_none() {
+            // No need to check local packages.
+            continue;
+        }
+        let license = match &pkg.license {
+            Some(license) => license,
+            None => {
+                tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
+                continue;
+            }
+        };
+        if !LICENSES.contains(&license.as_str()) {
+            // This is a specific exception because SGX is considered "third party".
+            // See https://github.com/rust-lang/rust/issues/62620 for more.
+            // In general, these should never be added and this exception
+            // should not be taken as precedent for any new target.
+            if pkg.name == "fortanix-sgx-abi" && pkg.license.as_deref() == Some("MPL-2.0") {
+                continue;
+            }
+            tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
+        }
+    }
+}
+
+/// Check that all licenses of tool dependencies are in the valid list in `LICENSES`.
+///
+/// Packages listed in `exceptions` are allowed for tools.
+fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], bad: &mut bool) {
     // Validate the EXCEPTIONS list hasn't changed.
     for (name, license) in exceptions {
         // Check that the package actually exists.
@@ -483,7 +583,7 @@ fn check_license_exceptions(
             // No need to check local packages.
             continue;
         }
-        if !runtime_ids.contains(&pkg.id) && exception_names.contains(&pkg.name.as_str()) {
+        if exception_names.contains(&pkg.name.as_str()) {
             continue;
         }
         let license = match &pkg.license {
@@ -494,13 +594,6 @@ fn check_license_exceptions(
             }
         };
         if !LICENSES.contains(&license.as_str()) {
-            if pkg.name == "fortanix-sgx-abi" {
-                // This is a specific exception because SGX is considered
-                // "third party". See
-                // https://github.com/rust-lang/rust/issues/62620 for more. In
-                // general, these should never be added.
-                continue;
-            }
             tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
         }
     }
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index aad57cacbb4..ff71ca53725 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -9,25 +9,33 @@ const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crat
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
 pub fn check(root: &Path, bad: &mut bool) {
-    // `Cargo.lock` of rust.
-    let path = root.join("Cargo.lock");
+    for &(workspace, _, _) in crate::deps::WORKSPACES {
+        // FIXME check other workspaces too
+        // `Cargo.lock` of rust.
+        let path = root.join(workspace).join("Cargo.lock");
 
-    // Open and read the whole file.
-    let cargo_lock = t!(fs::read_to_string(&path));
-
-    // Process each line.
-    for line in cargo_lock.lines() {
-        // Consider only source entries.
-        if !line.starts_with("source = ") {
+        if !path.exists() {
+            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
             continue;
         }
 
-        // Extract source value.
-        let source = line.split_once('=').unwrap().1.trim();
+        // Open and read the whole file.
+        let cargo_lock = t!(fs::read_to_string(&path));
+
+        // Process each line.
+        for line in cargo_lock.lines() {
+            // Consider only source entries.
+            if !line.starts_with("source = ") {
+                continue;
+            }
+
+            // Extract source value.
+            let source = line.split_once('=').unwrap().1.trim();
 
-        // Ensure source is allowed.
-        if !ALLOWED_SOURCES.contains(&&*source) {
-            tidy_error!(bad, "invalid source: {}", source);
+            // Ensure source is allowed.
+            if !ALLOWED_SOURCES.contains(&&*source) {
+                tidy_error!(bad, "invalid source: {}", source);
+            }
         }
     }
 }
diff --git a/tests/codegen/cross-crate-inlining/always-inline.rs b/tests/codegen/cross-crate-inlining/always-inline.rs
new file mode 100644
index 00000000000..f3f08bf116a
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/always-inline.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// aux-build:always.rs
+
+#![crate_type = "lib"]
+
+extern crate always;
+
+// Check that we inline a cross-crate call, even though it isn't a leaf
+#[no_mangle]
+pub fn outer() -> String {
+    // CHECK-NOT: call {{.*}}stem_fn
+    always::stem_fn()
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/always.rs b/tests/codegen/cross-crate-inlining/auxiliary/always.rs
new file mode 100644
index 00000000000..3670307ec81
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/always.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=always
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs
new file mode 100644
index 00000000000..963f087f22d
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/never.rs b/tests/codegen/cross-crate-inlining/auxiliary/never.rs
new file mode 100644
index 00000000000..e222a6dea38
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/never.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=never
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/leaf-inlining.rs b/tests/codegen/cross-crate-inlining/leaf-inlining.rs
new file mode 100644
index 00000000000..73b1a520b06
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/leaf-inlining.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=yes
+// aux-build:leaf.rs
+
+#![crate_type = "lib"]
+
+extern crate leaf;
+
+// Check that we inline a leaf cross-crate call
+#[no_mangle]
+pub fn leaf_outer() -> String {
+    // CHECK-NOT: call {{.*}}leaf_fn
+    leaf::leaf_fn()
+}
+
+// Check that we do not inline a non-leaf cross-crate call
+#[no_mangle]
+pub fn stem_outer() -> String {
+    // CHECK: call {{.*}}stem_fn
+    leaf::stem_fn()
+}
diff --git a/tests/codegen/cross-crate-inlining/never-inline.rs b/tests/codegen/cross-crate-inlining/never-inline.rs
new file mode 100644
index 00000000000..4e7bc3e5154
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/never-inline.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// aux-build:never.rs
+
+#![crate_type = "lib"]
+
+extern crate never;
+
+// Check that we do not inline a cross-crate call, even though it is a leaf
+#[no_mangle]
+pub fn outer() -> String {
+    // CHECK: call {{.*}}leaf_fn
+    never::leaf_fn()
+}
diff --git a/tests/codegen/vec-reserve-extend.rs b/tests/codegen/vec-reserve-extend.rs
new file mode 100644
index 00000000000..d95220104c2
--- /dev/null
+++ b/tests/codegen/vec-reserve-extend.rs
@@ -0,0 +1,14 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @should_reserve_once
+#[no_mangle]
+pub fn should_reserve_once(v: &mut Vec<u8>) {
+    // CHECK: tail call void @llvm.assume
+    v.try_reserve(3).unwrap();
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}do_reserve_and_handle
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+    v.extend([1, 2, 3]);
+}
diff --git a/tests/coverage-map/README.md b/tests/coverage-map/README.md
deleted file mode 100644
index 60d1352cd64..00000000000
--- a/tests/coverage-map/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-The tests in `./status-quo` were copied from `tests/run-coverage` in order to
-capture the current behavior of the instrumentor on non-trivial programs.
-The actual mappings have not been closely inspected.
-
-## Maintenance note
-
-These tests can be sensitive to small changes in MIR spans or MIR control flow,
-especially in HIR-to-MIR lowering or MIR optimizations.
-
-If you haven't touched the coverage code directly, and the `run-coverage` test
-suite still works, then it should usually be OK to just `--bless` these
-coverage mapping tests as necessary, without worrying too much about the exact
-changes.
diff --git a/tests/coverage-map/if.cov-map b/tests/coverage-map/if.cov-map
deleted file mode 100644
index 3cedb5ffbec..00000000000
--- a/tests/coverage-map/if.cov-map
+++ /dev/null
@@ -1,15 +0,0 @@
-Function name: if::main
-Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02]
-Number of files: 1
-- file 0 => global file 1
-Number of expressions: 2
-- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12)
-- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6)
-- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
-    = (c0 - c1)
-- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = (c1 + (c0 - c1))
-
diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs
deleted file mode 100644
index ed3f69bdc98..00000000000
--- a/tests/coverage-map/if.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --edition=2021
-
-fn main() {
-    let cond = std::env::args().len() == 1;
-    if cond {
-        println!("true");
-    }
-    println!("done");
-}
diff --git a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs
index c3210146d69..c3210146d69 100644
--- a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
+++ b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs
diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage
index 5797784f411..5797784f411 100644
--- a/tests/run-coverage-rustdoc/doctest.coverage
+++ b/tests/coverage-run-rustdoc/doctest.coverage
diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs
index 4006d723ce0..4006d723ce0 100644
--- a/tests/run-coverage-rustdoc/doctest.rs
+++ b/tests/coverage-run-rustdoc/doctest.rs
diff --git a/tests/coverage/README.md b/tests/coverage/README.md
new file mode 100644
index 00000000000..c72aa69c0ce
--- /dev/null
+++ b/tests/coverage/README.md
@@ -0,0 +1,16 @@
+The tests in this directory are shared by two different test modes, and can be
+run in multiple different ways:
+
+- `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings)
+- `./x.py test coverage-run` (runs a test binary and checks its coverage report)
+- `./x.py test coverage` (runs both `coverage-map` and `coverage-run`)
+
+## Maintenance note
+
+These tests can be sensitive to small changes in MIR spans or MIR control flow,
+especially in HIR-to-MIR lowering or MIR optimizations.
+
+If you haven't touched the coverage code directly, and the tests still pass in
+`coverage-run` mode, then it should usually be OK to just re-bless the mappings
+as necessary with `./x.py test coverage-map --bless`, without worrying too much
+about the exact changes.
diff --git a/tests/coverage-map/status-quo/abort.cov-map b/tests/coverage/abort.cov-map
index 45d3795eff8..45d3795eff8 100644
--- a/tests/coverage-map/status-quo/abort.cov-map
+++ b/tests/coverage/abort.cov-map
diff --git a/tests/run-coverage/abort.coverage b/tests/coverage/abort.coverage
index ceef6386780..ceef6386780 100644
--- a/tests/run-coverage/abort.coverage
+++ b/tests/coverage/abort.coverage
diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage/abort.rs
index 98264bdc1af..98264bdc1af 100644
--- a/tests/coverage-map/status-quo/abort.rs
+++ b/tests/coverage/abort.rs
diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage/assert.cov-map
index dd413123de7..dd413123de7 100644
--- a/tests/coverage-map/status-quo/assert.cov-map
+++ b/tests/coverage/assert.cov-map
diff --git a/tests/run-coverage/assert.coverage b/tests/coverage/assert.coverage
index 8b997724c4a..8b997724c4a 100644
--- a/tests/run-coverage/assert.coverage
+++ b/tests/coverage/assert.coverage
diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage/assert.rs
index 85e6662a6ad..85e6662a6ad 100644
--- a/tests/coverage-map/status-quo/assert.rs
+++ b/tests/coverage/assert.rs
diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage/async.cov-map
index 598791537ad..598791537ad 100644
--- a/tests/coverage-map/status-quo/async.cov-map
+++ b/tests/coverage/async.cov-map
diff --git a/tests/run-coverage/async.coverage b/tests/coverage/async.coverage
index 07bc16c2d92..07bc16c2d92 100644
--- a/tests/run-coverage/async.coverage
+++ b/tests/coverage/async.coverage
diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage/async.rs
index efd9e62d64e..efd9e62d64e 100644
--- a/tests/coverage-map/status-quo/async.rs
+++ b/tests/coverage/async.rs
diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage/async2.cov-map
index cc7aed9aee3..cc7aed9aee3 100644
--- a/tests/coverage-map/status-quo/async2.cov-map
+++ b/tests/coverage/async2.cov-map
diff --git a/tests/run-coverage/async2.coverage b/tests/coverage/async2.coverage
index fcb0a3aed64..fcb0a3aed64 100644
--- a/tests/run-coverage/async2.coverage
+++ b/tests/coverage/async2.coverage
diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage/async2.rs
index 2884ff297af..2884ff297af 100644
--- a/tests/coverage-map/status-quo/async2.rs
+++ b/tests/coverage/async2.rs
diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/coverage/auxiliary/inline_always_with_dead_code.rs
index 9dc50dae25a..9dc50dae25a 100644
--- a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
+++ b/tests/coverage/auxiliary/inline_always_with_dead_code.rs
diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/coverage/auxiliary/unused_mod_helper.rs
index 88c5dac65cb..88c5dac65cb 100644
--- a/tests/run-coverage/auxiliary/unused_mod_helper.rs
+++ b/tests/coverage/auxiliary/unused_mod_helper.rs
diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs
index c086ef21e1a..c086ef21e1a 100644
--- a/tests/run-coverage/auxiliary/used_crate.rs
+++ b/tests/coverage/auxiliary/used_crate.rs
diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs
index e8929de6b36..e8929de6b36 100644
--- a/tests/run-coverage/auxiliary/used_inline_crate.rs
+++ b/tests/coverage/auxiliary/used_inline_crate.rs
diff --git a/tests/coverage-map/status-quo/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map
index 0b8081acfa6..0b8081acfa6 100644
--- a/tests/coverage-map/status-quo/bad_counter_ids.cov-map
+++ b/tests/coverage/bad_counter_ids.cov-map
diff --git a/tests/run-coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage
index d69ebf160ea..d69ebf160ea 100644
--- a/tests/run-coverage/bad_counter_ids.coverage
+++ b/tests/coverage/bad_counter_ids.coverage
diff --git a/tests/coverage-map/status-quo/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs
index ef5460102b7..ef5460102b7 100644
--- a/tests/coverage-map/status-quo/bad_counter_ids.rs
+++ b/tests/coverage/bad_counter_ids.rs
diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage/closure.cov-map
index 522c1e73afe..522c1e73afe 100644
--- a/tests/coverage-map/status-quo/closure.cov-map
+++ b/tests/coverage/closure.cov-map
diff --git a/tests/run-coverage/closure.coverage b/tests/coverage/closure.coverage
index 67014f792c8..67014f792c8 100644
--- a/tests/run-coverage/closure.coverage
+++ b/tests/coverage/closure.coverage
diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage/closure.rs
index 16a2c4e33bd..16a2c4e33bd 100644
--- a/tests/coverage-map/status-quo/closure.rs
+++ b/tests/coverage/closure.rs
diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map
index 90eeb1a6686..90eeb1a6686 100644
--- a/tests/coverage-map/status-quo/closure_bug.cov-map
+++ b/tests/coverage/closure_bug.cov-map
diff --git a/tests/run-coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage
index f3299834bce..f3299834bce 100644
--- a/tests/run-coverage/closure_bug.coverage
+++ b/tests/coverage/closure_bug.coverage
diff --git a/tests/coverage-map/status-quo/closure_bug.rs b/tests/coverage/closure_bug.rs
index 739bc5f0b51..739bc5f0b51 100644
--- a/tests/coverage-map/status-quo/closure_bug.rs
+++ b/tests/coverage/closure_bug.rs
diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map
index b02c7e2e4c6..b02c7e2e4c6 100644
--- a/tests/coverage-map/status-quo/closure_macro.cov-map
+++ b/tests/coverage/closure_macro.cov-map
diff --git a/tests/run-coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage
index 0f2c917e090..0f2c917e090 100644
--- a/tests/run-coverage/closure_macro.coverage
+++ b/tests/coverage/closure_macro.coverage
diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage/closure_macro.rs
index 9b289141c2e..9b289141c2e 100644
--- a/tests/coverage-map/status-quo/closure_macro.rs
+++ b/tests/coverage/closure_macro.rs
diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index 7f8666948d9..7f8666948d9 100644
--- a/tests/coverage-map/status-quo/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage
index 74247f1bc6f..74247f1bc6f 100644
--- a/tests/run-coverage/closure_macro_async.coverage
+++ b/tests/coverage/closure_macro_async.coverage
diff --git a/tests/coverage-map/status-quo/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs
index b4275599e59..b4275599e59 100644
--- a/tests/coverage-map/status-quo/closure_macro_async.rs
+++ b/tests/coverage/closure_macro_async.rs
diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage/conditions.cov-map
index 7600d2d96bd..7600d2d96bd 100644
--- a/tests/coverage-map/status-quo/conditions.cov-map
+++ b/tests/coverage/conditions.cov-map
diff --git a/tests/run-coverage/conditions.coverage b/tests/coverage/conditions.coverage
index 473335ff641..473335ff641 100644
--- a/tests/run-coverage/conditions.coverage
+++ b/tests/coverage/conditions.coverage
diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage/conditions.rs
index fa7f2a116c2..fa7f2a116c2 100644
--- a/tests/coverage-map/status-quo/conditions.rs
+++ b/tests/coverage/conditions.rs
diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage/continue.cov-map
index 82f3d7c6095..82f3d7c6095 100644
--- a/tests/coverage-map/status-quo/continue.cov-map
+++ b/tests/coverage/continue.cov-map
diff --git a/tests/run-coverage/continue.coverage b/tests/coverage/continue.coverage
index 4916cac0038..4916cac0038 100644
--- a/tests/run-coverage/continue.coverage
+++ b/tests/coverage/continue.coverage
diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage/continue.rs
index 624aa98341b..624aa98341b 100644
--- a/tests/coverage-map/status-quo/continue.rs
+++ b/tests/coverage/continue.rs
diff --git a/tests/coverage-map/status-quo/coroutine.cov-map b/tests/coverage/coroutine.cov-map
index 2f4936d9ab8..2f4936d9ab8 100644
--- a/tests/coverage-map/status-quo/coroutine.cov-map
+++ b/tests/coverage/coroutine.cov-map
diff --git a/tests/run-coverage/coroutine.coverage b/tests/coverage/coroutine.coverage
index 3a9791a0dbd..3a9791a0dbd 100644
--- a/tests/run-coverage/coroutine.coverage
+++ b/tests/coverage/coroutine.coverage
diff --git a/tests/coverage-map/status-quo/coroutine.rs b/tests/coverage/coroutine.rs
index 86d19af6f4f..86d19af6f4f 100644
--- a/tests/coverage-map/status-quo/coroutine.rs
+++ b/tests/coverage/coroutine.rs
diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage/dead_code.cov-map
index 0b8a40a8cde..0b8a40a8cde 100644
--- a/tests/coverage-map/status-quo/dead_code.cov-map
+++ b/tests/coverage/dead_code.cov-map
diff --git a/tests/run-coverage/dead_code.coverage b/tests/coverage/dead_code.coverage
index c4ee9f23f08..c4ee9f23f08 100644
--- a/tests/run-coverage/dead_code.coverage
+++ b/tests/coverage/dead_code.coverage
diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage/dead_code.rs
index 3492712a6f9..3492712a6f9 100644
--- a/tests/coverage-map/status-quo/dead_code.rs
+++ b/tests/coverage/dead_code.rs
diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map
index 203d1048b05..203d1048b05 100644
--- a/tests/coverage-map/status-quo/drop_trait.cov-map
+++ b/tests/coverage/drop_trait.cov-map
diff --git a/tests/run-coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage
index 2c9439a93b1..2c9439a93b1 100644
--- a/tests/run-coverage/drop_trait.coverage
+++ b/tests/coverage/drop_trait.coverage
diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage/drop_trait.rs
index 7b062719c6b..7b062719c6b 100644
--- a/tests/coverage-map/status-quo/drop_trait.rs
+++ b/tests/coverage/drop_trait.rs
diff --git a/tests/coverage-map/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map
index 6e26c61aac9..6e26c61aac9 100644
--- a/tests/coverage-map/fn_sig_into_try.cov-map
+++ b/tests/coverage/fn_sig_into_try.cov-map
diff --git a/tests/run-coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage
index f1ddb1da780..f1ddb1da780 100644
--- a/tests/run-coverage/fn_sig_into_try.coverage
+++ b/tests/coverage/fn_sig_into_try.coverage
diff --git a/tests/coverage-map/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs
index 92850c8a188..92850c8a188 100644
--- a/tests/coverage-map/fn_sig_into_try.rs
+++ b/tests/coverage/fn_sig_into_try.rs
diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage/generics.cov-map
index 6079a433cd0..6079a433cd0 100644
--- a/tests/coverage-map/status-quo/generics.cov-map
+++ b/tests/coverage/generics.cov-map
diff --git a/tests/run-coverage/generics.coverage b/tests/coverage/generics.coverage
index 09839183566..09839183566 100644
--- a/tests/run-coverage/generics.coverage
+++ b/tests/coverage/generics.coverage
diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage/generics.rs
index bf4c2d8d685..bf4c2d8d685 100644
--- a/tests/coverage-map/status-quo/generics.rs
+++ b/tests/coverage/generics.rs
diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage/if.cov-map
index 391a69e0e82..391a69e0e82 100644
--- a/tests/coverage-map/status-quo/if.cov-map
+++ b/tests/coverage/if.cov-map
diff --git a/tests/run-coverage/if.coverage b/tests/coverage/if.coverage
index 2e6845190aa..2e6845190aa 100644
--- a/tests/run-coverage/if.coverage
+++ b/tests/coverage/if.coverage
diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage/if.rs
index 8ad5042ff7b..8ad5042ff7b 100644
--- a/tests/coverage-map/status-quo/if.rs
+++ b/tests/coverage/if.rs
diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage/if_else.cov-map
index da692ca3aa2..da692ca3aa2 100644
--- a/tests/coverage-map/status-quo/if_else.cov-map
+++ b/tests/coverage/if_else.cov-map
diff --git a/tests/run-coverage/if_else.coverage b/tests/coverage/if_else.coverage
index 0274401f004..0274401f004 100644
--- a/tests/run-coverage/if_else.coverage
+++ b/tests/coverage/if_else.coverage
diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage/if_else.rs
index 3244e1e3afd..3244e1e3afd 100644
--- a/tests/coverage-map/status-quo/if_else.rs
+++ b/tests/coverage/if_else.rs
diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map
index 958b423f24c..958b423f24c 100644
--- a/tests/coverage-map/status-quo/inline-dead.cov-map
+++ b/tests/coverage/inline-dead.cov-map
diff --git a/tests/run-coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage
index de96aa17acd..de96aa17acd 100644
--- a/tests/run-coverage/inline-dead.coverage
+++ b/tests/coverage/inline-dead.coverage
diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage/inline-dead.rs
index 854fa062967..854fa062967 100644
--- a/tests/coverage-map/status-quo/inline-dead.rs
+++ b/tests/coverage/inline-dead.rs
diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage/inline.cov-map
index 72b10fd0cc2..72b10fd0cc2 100644
--- a/tests/coverage-map/status-quo/inline.cov-map
+++ b/tests/coverage/inline.cov-map
diff --git a/tests/run-coverage/inline.coverage b/tests/coverage/inline.coverage
index 6efd9a0830b..6efd9a0830b 100644
--- a/tests/run-coverage/inline.coverage
+++ b/tests/coverage/inline.coverage
diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage/inline.rs
index 9cfab9ddbad..9cfab9ddbad 100644
--- a/tests/coverage-map/status-quo/inline.rs
+++ b/tests/coverage/inline.rs
diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage/inner_items.cov-map
index 3f39d74efba..3f39d74efba 100644
--- a/tests/coverage-map/status-quo/inner_items.cov-map
+++ b/tests/coverage/inner_items.cov-map
diff --git a/tests/run-coverage/inner_items.coverage b/tests/coverage/inner_items.coverage
index 65493bcd9db..65493bcd9db 100644
--- a/tests/run-coverage/inner_items.coverage
+++ b/tests/coverage/inner_items.coverage
diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage/inner_items.rs
index bcb62b3031c..bcb62b3031c 100644
--- a/tests/coverage-map/status-quo/inner_items.rs
+++ b/tests/coverage/inner_items.rs
diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map
index f5db3a89750..f5db3a89750 100644
--- a/tests/coverage-map/status-quo/issue-83601.cov-map
+++ b/tests/coverage/issue-83601.cov-map
diff --git a/tests/run-coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage
index 7995332cad3..7995332cad3 100644
--- a/tests/run-coverage/issue-83601.coverage
+++ b/tests/coverage/issue-83601.coverage
diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage/issue-83601.rs
index 0b72a81947c..0b72a81947c 100644
--- a/tests/coverage-map/status-quo/issue-83601.rs
+++ b/tests/coverage/issue-83601.rs
diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index 82582b309bf..82582b309bf 100644
--- a/tests/coverage-map/status-quo/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
diff --git a/tests/run-coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage
index e693866e277..e693866e277 100644
--- a/tests/run-coverage/issue-84561.coverage
+++ b/tests/coverage/issue-84561.coverage
diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage/issue-84561.rs
index facf5b5b4cf..facf5b5b4cf 100644
--- a/tests/coverage-map/status-quo/issue-84561.rs
+++ b/tests/coverage/issue-84561.rs
diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map
new file mode 100644
index 00000000000..d1c449b9a35
--- /dev/null
+++ b/tests/coverage/issue-85461.cov-map
@@ -0,0 +1,8 @@
+Function name: issue_85461::main
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 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 + 8, 1) to (start + 3, 2)
+
diff --git a/tests/run-coverage/issue-85461.coverage b/tests/coverage/issue-85461.coverage
index cbc910664d0..cbc910664d0 100644
--- a/tests/run-coverage/issue-85461.coverage
+++ b/tests/coverage/issue-85461.coverage
diff --git a/tests/run-coverage/issue-85461.rs b/tests/coverage/issue-85461.rs
index 9d4c90a827e..9d4c90a827e 100644
--- a/tests/run-coverage/issue-85461.rs
+++ b/tests/coverage/issue-85461.rs
diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map
index c2c6e9a6516..c2c6e9a6516 100644
--- a/tests/coverage-map/status-quo/issue-93054.cov-map
+++ b/tests/coverage/issue-93054.cov-map
diff --git a/tests/run-coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage
index 15f225326a4..15f225326a4 100644
--- a/tests/run-coverage/issue-93054.coverage
+++ b/tests/coverage/issue-93054.coverage
diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage/issue-93054.rs
index da546cfeef8..da546cfeef8 100644
--- a/tests/coverage-map/status-quo/issue-93054.rs
+++ b/tests/coverage/issue-93054.rs
diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map
index 0ad393c40fa..0ad393c40fa 100644
--- a/tests/coverage-map/status-quo/lazy_boolean.cov-map
+++ b/tests/coverage/lazy_boolean.cov-map
diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage
index 8f14082ef68..8f14082ef68 100644
--- a/tests/run-coverage/lazy_boolean.coverage
+++ b/tests/coverage/lazy_boolean.coverage
diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs
index bb6219e851c..bb6219e851c 100644
--- a/tests/coverage-map/status-quo/lazy_boolean.rs
+++ b/tests/coverage/lazy_boolean.rs
diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map
index 97aebf9b18a..97aebf9b18a 100644
--- a/tests/coverage-map/long_and_wide.cov-map
+++ b/tests/coverage/long_and_wide.cov-map
diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage
new file mode 100644
index 00000000000..d7d29ca40cd
--- /dev/null
+++ b/tests/coverage/long_and_wide.coverage
@@ -0,0 +1,151 @@
+   LL|       |// compile-flags: --edition=2021
+   LL|       |// ignore-tidy-linelength
+   LL|       |
+   LL|       |// This file deliberately contains line and column numbers larger than 127,
+   LL|       |// to verify that `coverage-dump`'s ULEB128 parser can handle them.
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    wide_function();
+   LL|      1|    long_function();
+   LL|      1|    far_function();
+   LL|      1|}
+   LL|       |
+   LL|       |#[rustfmt::skip]
+   LL|      1|fn wide_function() { /*                                                                                                           */ (); }
+   LL|       |
+   LL|      1|fn long_function() {
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|    //
+   LL|      1|}
+   LL|       |
+   LL|      1|fn far_function() {}
+
diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage/long_and_wide.rs
index a7cbcd48027..a7cbcd48027 100644
--- a/tests/coverage-map/long_and_wide.rs
+++ b/tests/coverage/long_and_wide.rs
diff --git a/tests/coverage-map/status-quo/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map
index 75018442d07..75018442d07 100644
--- a/tests/coverage-map/status-quo/loop_break_value.cov-map
+++ b/tests/coverage/loop_break_value.cov-map
diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage
index 1f0630636dd..1f0630636dd 100644
--- a/tests/run-coverage/loop_break_value.coverage
+++ b/tests/coverage/loop_break_value.coverage
diff --git a/tests/coverage-map/status-quo/loop_break_value.rs b/tests/coverage/loop_break_value.rs
index dbc4fad7a23..dbc4fad7a23 100644
--- a/tests/coverage-map/status-quo/loop_break_value.rs
+++ b/tests/coverage/loop_break_value.rs
diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map
index 813583a9de7..813583a9de7 100644
--- a/tests/coverage-map/status-quo/loops_branches.cov-map
+++ b/tests/coverage/loops_branches.cov-map
diff --git a/tests/run-coverage/loops_branches.coverage b/tests/coverage/loops_branches.coverage
index 8cd6f1be3f7..8cd6f1be3f7 100644
--- a/tests/run-coverage/loops_branches.coverage
+++ b/tests/coverage/loops_branches.coverage
diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage/loops_branches.rs
index f3a343bcc1f..f3a343bcc1f 100644
--- a/tests/coverage-map/status-quo/loops_branches.rs
+++ b/tests/coverage/loops_branches.rs
diff --git a/tests/coverage-map/status-quo/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map
index d63407a99c3..d63407a99c3 100644
--- a/tests/coverage-map/status-quo/match_or_pattern.cov-map
+++ b/tests/coverage/match_or_pattern.cov-map
diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage
index 94c7967215c..94c7967215c 100644
--- a/tests/run-coverage/match_or_pattern.coverage
+++ b/tests/coverage/match_or_pattern.coverage
diff --git a/tests/coverage-map/status-quo/match_or_pattern.rs b/tests/coverage/match_or_pattern.rs
index ab7aee51d1b..ab7aee51d1b 100644
--- a/tests/coverage-map/status-quo/match_or_pattern.rs
+++ b/tests/coverage/match_or_pattern.rs
diff --git a/tests/coverage-map/status-quo/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map
index 35d92594e75..35d92594e75 100644
--- a/tests/coverage-map/status-quo/nested_loops.cov-map
+++ b/tests/coverage/nested_loops.cov-map
diff --git a/tests/run-coverage/nested_loops.coverage b/tests/coverage/nested_loops.coverage
index 143d0d26aa7..143d0d26aa7 100644
--- a/tests/run-coverage/nested_loops.coverage
+++ b/tests/coverage/nested_loops.coverage
diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage/nested_loops.rs
index 4c7c7842796..4c7c7842796 100644
--- a/tests/coverage-map/status-quo/nested_loops.rs
+++ b/tests/coverage/nested_loops.rs
diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map
index 05b6448bbd2..05b6448bbd2 100644
--- a/tests/coverage-map/status-quo/no_cov_crate.cov-map
+++ b/tests/coverage/no_cov_crate.cov-map
diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage
index f5a0322bf3e..f5a0322bf3e 100644
--- a/tests/run-coverage/no_cov_crate.coverage
+++ b/tests/coverage/no_cov_crate.coverage
diff --git a/tests/coverage-map/status-quo/no_cov_crate.rs b/tests/coverage/no_cov_crate.rs
index e12e4bc55e3..e12e4bc55e3 100644
--- a/tests/coverage-map/status-quo/no_cov_crate.rs
+++ b/tests/coverage/no_cov_crate.rs
diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage/overflow.cov-map
index bfffd9b2ab5..39a5c05f879 100644
--- a/tests/coverage-map/status-quo/overflow.cov-map
+++ b/tests/coverage/overflow.cov-map
@@ -1,5 +1,5 @@
 Function name: overflow::main
-Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0f, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02]
+Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
@@ -12,7 +12,7 @@ Number of expressions: 8
 - expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add)
 - expression 7 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 9
-- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 27)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24)
     = (c0 + (c1 + (c2 + c3)))
 - Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26)
@@ -27,14 +27,14 @@ Number of file 0 mappings: 9
 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2)
 
 Function name: overflow::might_overflow
-Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02]
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 18)
+- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18)
 - Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
     = (c0 - c1)
diff --git a/tests/run-coverage/overflow.coverage b/tests/coverage/overflow.coverage
index cee076e88cd..4f8dffc0c48 100644
--- a/tests/run-coverage/overflow.coverage
+++ b/tests/coverage/overflow.coverage
@@ -1,4 +1,5 @@
    LL|       |#![allow(unused_assignments)]
+   LL|       |// compile-flags: -Coverflow-checks=yes
    LL|       |// failure-status: 101
    LL|       |
    LL|      4|fn might_overflow(to_add: u32) -> u32 {
diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage/overflow.rs
index bbb65c1b35d..1c40771b274 100644
--- a/tests/coverage-map/status-quo/overflow.rs
+++ b/tests/coverage/overflow.rs
@@ -1,4 +1,5 @@
 #![allow(unused_assignments)]
+// compile-flags: -Coverflow-checks=yes
 // failure-status: 101
 
 fn might_overflow(to_add: u32) -> u32 {
diff --git a/tests/coverage-map/status-quo/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map
index f6089ce55ae..f6089ce55ae 100644
--- a/tests/coverage-map/status-quo/panic_unwind.cov-map
+++ b/tests/coverage/panic_unwind.cov-map
diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/coverage/panic_unwind.coverage
index 2b0777ef215..2b0777ef215 100644
--- a/tests/run-coverage/panic_unwind.coverage
+++ b/tests/coverage/panic_unwind.coverage
diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage/panic_unwind.rs
index 638d2eb6aaa..638d2eb6aaa 100644
--- a/tests/coverage-map/status-quo/panic_unwind.rs
+++ b/tests/coverage/panic_unwind.rs
diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map
index 3549116db7a..3549116db7a 100644
--- a/tests/coverage-map/status-quo/partial_eq.cov-map
+++ b/tests/coverage/partial_eq.cov-map
diff --git a/tests/run-coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage
index c6d9ad6cf27..c6d9ad6cf27 100644
--- a/tests/run-coverage/partial_eq.coverage
+++ b/tests/coverage/partial_eq.coverage
diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage/partial_eq.rs
index dd8b42c18ce..dd8b42c18ce 100644
--- a/tests/coverage-map/status-quo/partial_eq.rs
+++ b/tests/coverage/partial_eq.rs
diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map
index f1691ffc5e6..f1691ffc5e6 100644
--- a/tests/coverage-map/status-quo/simple_loop.cov-map
+++ b/tests/coverage/simple_loop.cov-map
diff --git a/tests/run-coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage
index 691c6cd1e7d..691c6cd1e7d 100644
--- a/tests/run-coverage/simple_loop.coverage
+++ b/tests/coverage/simple_loop.coverage
diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage/simple_loop.rs
index 6f7f23475b8..6f7f23475b8 100644
--- a/tests/coverage-map/status-quo/simple_loop.rs
+++ b/tests/coverage/simple_loop.rs
diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage/simple_match.cov-map
index 4a32745d292..4a32745d292 100644
--- a/tests/coverage-map/status-quo/simple_match.cov-map
+++ b/tests/coverage/simple_match.cov-map
diff --git a/tests/run-coverage/simple_match.coverage b/tests/coverage/simple_match.coverage
index 7f5dd3bb646..7f5dd3bb646 100644
--- a/tests/run-coverage/simple_match.coverage
+++ b/tests/coverage/simple_match.coverage
diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage/simple_match.rs
index be99e59a826..be99e59a826 100644
--- a/tests/coverage-map/status-quo/simple_match.rs
+++ b/tests/coverage/simple_match.rs
diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map
index db027f3dc32..3cbda6fbe1a 100644
--- a/tests/coverage-map/status-quo/sort_groups.cov-map
+++ b/tests/coverage/sort_groups.cov-map
@@ -28,6 +28,21 @@ Number of file 0 mappings: 4
 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
     = (c1 + (c0 - c1))
 
+Function name: sort_groups::generic_fn::<char>
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12)
+- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6)
+- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
+    = (c1 + (c0 - c1))
+
 Function name: sort_groups::generic_fn::<i32>
 Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02]
 Number of files: 1
@@ -44,19 +59,19 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: sort_groups::main
-Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 06, 01, 04, 0d, 00, 04, 0e, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02]
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub)
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 13)
-- Code(Zero) at (prev + 4, 14) to (start + 2, 6)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35)
+- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
-    = (c0 - Zero)
+    = (c0 - c1)
 - Code(Expression(1, Add)) at (prev + 1, 5) to (start + 2, 2)
-    = (Zero + (c0 - Zero))
+    = (c1 + (c0 - c1))
 
 Function name: sort_groups::other_fn
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11]
diff --git a/tests/run-coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage
index 8733bf48a9c..c70d7b3b282 100644
--- a/tests/run-coverage/sort_groups.coverage
+++ b/tests/coverage/sort_groups.coverage
@@ -7,7 +7,7 @@
    LL|      1|    let cond = std::env::args().len() > 1;
    LL|      1|    generic_fn::<()>(cond);
    LL|      1|    generic_fn::<&'static str>(!cond);
-   LL|      1|    if false {
+   LL|      1|    if std::hint::black_box(false) {
    LL|      0|        generic_fn::<char>(cond);
    LL|      1|    }
    LL|      1|    generic_fn::<i32>(cond);
diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage/sort_groups.rs
index f89f9f3ec61..5adbbc6a87d 100644
--- a/tests/coverage-map/status-quo/sort_groups.rs
+++ b/tests/coverage/sort_groups.rs
@@ -7,7 +7,7 @@ fn main() {
     let cond = std::env::args().len() > 1;
     generic_fn::<()>(cond);
     generic_fn::<&'static str>(!cond);
-    if false {
+    if std::hint::black_box(false) {
         generic_fn::<char>(cond);
     }
     generic_fn::<i32>(cond);
diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage/test_harness.cov-map
index 6940d2e2824..6940d2e2824 100644
--- a/tests/coverage-map/status-quo/test_harness.cov-map
+++ b/tests/coverage/test_harness.cov-map
diff --git a/tests/run-coverage/test_harness.coverage b/tests/coverage/test_harness.coverage
index ff6009f6fce..ff6009f6fce 100644
--- a/tests/run-coverage/test_harness.coverage
+++ b/tests/coverage/test_harness.coverage
diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage/test_harness.rs
index 12a755734c1..12a755734c1 100644
--- a/tests/coverage-map/status-quo/test_harness.rs
+++ b/tests/coverage/test_harness.rs
diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map
index 7fe3146b080..7fe3146b080 100644
--- a/tests/coverage-map/status-quo/tight_inf_loop.cov-map
+++ b/tests/coverage/tight_inf_loop.cov-map
diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/coverage/tight_inf_loop.coverage
index c15c76b3aba..c15c76b3aba 100644
--- a/tests/run-coverage/tight_inf_loop.coverage
+++ b/tests/coverage/tight_inf_loop.coverage
diff --git a/tests/coverage-map/status-quo/tight_inf_loop.rs b/tests/coverage/tight_inf_loop.rs
index cef99027aaa..cef99027aaa 100644
--- a/tests/coverage-map/status-quo/tight_inf_loop.rs
+++ b/tests/coverage/tight_inf_loop.rs
diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage/trivial.cov-map
index 874e294a1c4..874e294a1c4 100644
--- a/tests/coverage-map/trivial.cov-map
+++ b/tests/coverage/trivial.cov-map
diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage
new file mode 100644
index 00000000000..4f417979ef9
--- /dev/null
+++ b/tests/coverage/trivial.coverage
@@ -0,0 +1,4 @@
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|      1|fn main() {}
+
diff --git a/tests/coverage-map/trivial.rs b/tests/coverage/trivial.rs
index d0a9b44fb36..d0a9b44fb36 100644
--- a/tests/coverage-map/trivial.rs
+++ b/tests/coverage/trivial.rs
diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map
index 8367103a21a..8367103a21a 100644
--- a/tests/coverage-map/status-quo/try_error_result.cov-map
+++ b/tests/coverage/try_error_result.cov-map
diff --git a/tests/run-coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage
index 5d48cbd62f2..5d48cbd62f2 100644
--- a/tests/run-coverage/try_error_result.coverage
+++ b/tests/coverage/try_error_result.coverage
diff --git a/tests/coverage-map/status-quo/try_error_result.rs b/tests/coverage/try_error_result.rs
index 557cbf22bfa..557cbf22bfa 100644
--- a/tests/coverage-map/status-quo/try_error_result.rs
+++ b/tests/coverage/try_error_result.rs
diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage/unreachable.cov-map
index 495419820c1..495419820c1 100644
--- a/tests/coverage-map/unreachable.cov-map
+++ b/tests/coverage/unreachable.cov-map
diff --git a/tests/run-coverage/unreachable.coverage b/tests/coverage/unreachable.coverage
index fa0ac9ccfa1..fa0ac9ccfa1 100644
--- a/tests/run-coverage/unreachable.coverage
+++ b/tests/coverage/unreachable.coverage
diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage/unreachable.rs
index 6385bfa160d..6385bfa160d 100644
--- a/tests/coverage-map/unreachable.rs
+++ b/tests/coverage/unreachable.rs
diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage/unused.cov-map
index 9383d1e90ac..9383d1e90ac 100644
--- a/tests/coverage-map/status-quo/unused.cov-map
+++ b/tests/coverage/unused.cov-map
diff --git a/tests/run-coverage/unused.coverage b/tests/coverage/unused.coverage
index 056ffeb021a..056ffeb021a 100644
--- a/tests/run-coverage/unused.coverage
+++ b/tests/coverage/unused.coverage
diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage/unused.rs
index d985af13547..d985af13547 100644
--- a/tests/coverage-map/status-quo/unused.rs
+++ b/tests/coverage/unused.rs
diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map
new file mode 100644
index 00000000000..241cb2610ff
--- /dev/null
+++ b/tests/coverage/unused_mod.cov-map
@@ -0,0 +1,16 @@
+Function name: unused_mod::main
+Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 2
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2)
+
+Function name: unused_mod::unused_module::never_called_function (unused)
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 2, 1) to (start + 2, 2)
+
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/coverage/unused_mod.coverage
index a8fa24ac6a7..a8fa24ac6a7 100644
--- a/tests/run-coverage/unused_mod.coverage
+++ b/tests/coverage/unused_mod.coverage
diff --git a/tests/run-coverage/unused_mod.rs b/tests/coverage/unused_mod.rs
index 6e62839c998..6e62839c998 100644
--- a/tests/run-coverage/unused_mod.rs
+++ b/tests/coverage/unused_mod.rs
diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map
new file mode 100644
index 00000000000..9c06eab7005
--- /dev/null
+++ b/tests/coverage/uses_crate.cov-map
@@ -0,0 +1,40 @@
+Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 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 + 27, 1) to (start + 2, 2)
+
+Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 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 + 19, 1) to (start + 2, 2)
+
+Function name: used_crate::used_only_from_bin_crate_generic_function::<&str>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 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 + 19, 1) to (start + 2, 2)
+
+Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 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 + 31, 1) to (start + 2, 2)
+
+Function name: uses_crate::main
+Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02]
+Number of files: 1
+- file 0 => global file 2
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2)
+
diff --git a/tests/run-coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage
index 50d92102a10..50d92102a10 100644
--- a/tests/run-coverage/uses_crate.coverage
+++ b/tests/coverage/uses_crate.coverage
diff --git a/tests/run-coverage/uses_crate.rs b/tests/coverage/uses_crate.rs
index ab203ad781d..ab203ad781d 100644
--- a/tests/run-coverage/uses_crate.rs
+++ b/tests/coverage/uses_crate.rs
diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map
new file mode 100644
index 00000000000..6b621825c88
--- /dev/null
+++ b/tests/coverage/uses_inline_crate.cov-map
@@ -0,0 +1,55 @@
+Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 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 + 44, 1) to (start + 2, 2)
+
+Function name: used_inline_crate::used_inline_function
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15)
+- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6)
+- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2)
+    = (c1 + (c0 - c1))
+
+Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>
+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 + 33, 1) to (start + 2, 2)
+
+Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str>
+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 + 33, 1) to (start + 2, 2)
+
+Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 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 + 49, 1) to (start + 2, 2)
+
+Function name: uses_inline_crate::main
+Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02]
+Number of files: 1
+- file 0 => global file 2
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2)
+
diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage
index cc0e01ffde1..cc0e01ffde1 100644
--- a/tests/run-coverage/uses_inline_crate.coverage
+++ b/tests/coverage/uses_inline_crate.coverage
diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/coverage/uses_inline_crate.rs
index d7b4c3c057f..d7b4c3c057f 100644
--- a/tests/run-coverage/uses_inline_crate.rs
+++ b/tests/coverage/uses_inline_crate.rs
diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage/while.cov-map
index af250f3fb71..af250f3fb71 100644
--- a/tests/coverage-map/status-quo/while.cov-map
+++ b/tests/coverage/while.cov-map
diff --git a/tests/run-coverage/while.coverage b/tests/coverage/while.coverage
index c9d497651c9..c9d497651c9 100644
--- a/tests/run-coverage/while.coverage
+++ b/tests/coverage/while.coverage
diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage/while.rs
index 781b90b3566..781b90b3566 100644
--- a/tests/coverage-map/status-quo/while.rs
+++ b/tests/coverage/while.rs
diff --git a/tests/coverage-map/status-quo/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map
index 369ebe891f1..369ebe891f1 100644
--- a/tests/coverage-map/status-quo/while_early_ret.cov-map
+++ b/tests/coverage/while_early_ret.cov-map
diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage
index 49d39d36603..49d39d36603 100644
--- a/tests/run-coverage/while_early_ret.coverage
+++ b/tests/coverage/while_early_ret.coverage
diff --git a/tests/coverage-map/status-quo/while_early_ret.rs b/tests/coverage/while_early_ret.rs
index b2f0eee2cc0..b2f0eee2cc0 100644
--- a/tests/coverage-map/status-quo/while_early_ret.rs
+++ b/tests/coverage/while_early_ret.rs
diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage/yield.cov-map
index c9c9709fa4f..c9c9709fa4f 100644
--- a/tests/coverage-map/status-quo/yield.cov-map
+++ b/tests/coverage/yield.cov-map
diff --git a/tests/run-coverage/yield.coverage b/tests/coverage/yield.coverage
index d7e455f211e..d7e455f211e 100644
--- a/tests/run-coverage/yield.coverage
+++ b/tests/coverage/yield.coverage
diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage/yield.rs
index b7e2ba31b59..b7e2ba31b59 100644
--- a/tests/coverage-map/status-quo/yield.rs
+++ b/tests/coverage/yield.rs
diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs
index aa3cf023a71..fea8109223a 100644
--- a/tests/debuginfo/simple-struct.rs
+++ b/tests/debuginfo/simple-struct.rs
@@ -1,7 +1,7 @@
 // min-lldb-version: 310
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
-// compile-flags:-g
+// compile-flags: -g -Zmir-enable-passes=-CheckAlignment
 
 // === GDB TESTS ===================================================================================
 
diff --git a/tests/mir-opt/building/while_storage.rs b/tests/mir-opt/building/while_storage.rs
new file mode 100644
index 00000000000..b06c1639c3f
--- /dev/null
+++ b/tests/mir-opt/building/while_storage.rs
@@ -0,0 +1,60 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// Test that we correctly generate StorageDead statements for while loop
+// conditions on all branches
+// compile-flags: -Zmir-opt-level=0
+
+fn get_bool(c: bool) -> bool {
+    c
+}
+
+// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir
+fn while_loop(c: bool) {
+    // CHECK-LABEL: fn while_loop(
+    // CHECK: bb0: {
+    // CHECK-NEXT:     goto -> bb1;
+    // CHECK: bb1: {
+    // CHECK-NEXT:     StorageLive(_3);
+    // CHECK-NEXT:     StorageLive(_2);
+    // CHECK-NEXT:     _2 = _1;
+    // CHECK-NEXT:     _3 = get_bool(move _2) -> [return: bb2, unwind
+    // CHECK: bb2: {
+    // CHECK-NEXT:     switchInt(move _3) -> [0: bb3, otherwise: bb4];
+    // CHECK: bb3: {
+    // CHECK-NEXT:     StorageDead(_2);
+    // CHECK-NEXT:     StorageLive(_9);
+    // CHECK-NEXT:     _0 = const ();
+    // CHECK-NEXT:     StorageDead(_9);
+    // CHECK-NEXT:     goto -> bb8;
+    // CHECK: bb4: {
+    // CHECK-NEXT:     StorageDead(_2);
+    // CHECK-NEXT:     StorageLive(_5);
+    // CHECK-NEXT:     StorageLive(_4);
+    // CHECK-NEXT:     _4 = _1;
+    // CHECK-NEXT:     _5 = get_bool(move _4) -> [return: bb5, unwind
+    // CHECK: bb5: {
+    // CHECK-NEXT:     switchInt(move _5) -> [0: bb6, otherwise: bb7];
+    // CHECK: bb6: {
+    // CHECK-NEXT:     StorageDead(_4);
+    // CHECK-NEXT:     _6 = const ();
+    // CHECK-NEXT:     StorageDead(_5);
+    // CHECK-NEXT:     StorageDead(_3);
+    // CHECK-NEXT:     goto -> bb1;
+    // CHECK: bb7: {
+    // CHECK-NEXT:     StorageDead(_4);
+    // CHECK-NEXT:     _0 = const ();
+    // CHECK-NEXT:     StorageDead(_5);
+    // CHECK-NEXT:     goto -> bb8;
+    // CHECK: bb8: {
+    // CHECK-NEXT:     StorageDead(_3);
+    // CHECK-NEXT:     return;
+
+    while get_bool(c) {
+        if get_bool(c) {
+            break;
+        }
+    }
+}
+
+fn main() {
+    while_loop(false);
+}
diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir
new file mode 100644
index 00000000000..26c82edf2d5
--- /dev/null
+++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,70 @@
+// MIR for `while_loop` after PreCodegen
+
+fn while_loop(_1: bool) -> () {
+    debug c => _1;
+    let mut _0: ();
+    let mut _2: bool;
+    let mut _3: bool;
+    let mut _4: bool;
+    let mut _5: bool;
+    let mut _6: ();
+    let mut _7: !;
+    let mut _8: !;
+    let _9: ();
+    let mut _10: !;
+
+    bb0: {
+        goto -> bb1;
+    }
+
+    bb1: {
+        StorageLive(_3);
+        StorageLive(_2);
+        _2 = _1;
+        _3 = get_bool(move _2) -> [return: bb2, unwind unreachable];
+    }
+
+    bb2: {
+        switchInt(move _3) -> [0: bb3, otherwise: bb4];
+    }
+
+    bb3: {
+        StorageDead(_2);
+        StorageLive(_9);
+        _0 = const ();
+        StorageDead(_9);
+        goto -> bb8;
+    }
+
+    bb4: {
+        StorageDead(_2);
+        StorageLive(_5);
+        StorageLive(_4);
+        _4 = _1;
+        _5 = get_bool(move _4) -> [return: bb5, unwind unreachable];
+    }
+
+    bb5: {
+        switchInt(move _5) -> [0: bb6, otherwise: bb7];
+    }
+
+    bb6: {
+        StorageDead(_4);
+        _6 = const ();
+        StorageDead(_5);
+        StorageDead(_3);
+        goto -> bb1;
+    }
+
+    bb7: {
+        StorageDead(_4);
+        _0 = const ();
+        StorageDead(_5);
+        goto -> bb8;
+    }
+
+    bb8: {
+        StorageDead(_3);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 00000000000..1bb72074846
--- /dev/null
+++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,70 @@
+// MIR for `while_loop` after PreCodegen
+
+fn while_loop(_1: bool) -> () {
+    debug c => _1;
+    let mut _0: ();
+    let mut _2: bool;
+    let mut _3: bool;
+    let mut _4: bool;
+    let mut _5: bool;
+    let mut _6: ();
+    let mut _7: !;
+    let mut _8: !;
+    let _9: ();
+    let mut _10: !;
+
+    bb0: {
+        goto -> bb1;
+    }
+
+    bb1: {
+        StorageLive(_3);
+        StorageLive(_2);
+        _2 = _1;
+        _3 = get_bool(move _2) -> [return: bb2, unwind continue];
+    }
+
+    bb2: {
+        switchInt(move _3) -> [0: bb3, otherwise: bb4];
+    }
+
+    bb3: {
+        StorageDead(_2);
+        StorageLive(_9);
+        _0 = const ();
+        StorageDead(_9);
+        goto -> bb8;
+    }
+
+    bb4: {
+        StorageDead(_2);
+        StorageLive(_5);
+        StorageLive(_4);
+        _4 = _1;
+        _5 = get_bool(move _4) -> [return: bb5, unwind continue];
+    }
+
+    bb5: {
+        switchInt(move _5) -> [0: bb6, otherwise: bb7];
+    }
+
+    bb6: {
+        StorageDead(_4);
+        _6 = const ();
+        StorageDead(_5);
+        StorageDead(_3);
+        goto -> bb1;
+    }
+
+    bb7: {
+        StorageDead(_4);
+        _0 = const ();
+        StorageDead(_5);
+        goto -> bb8;
+    }
+
+    bb8: {
+        StorageDead(_3);
+        return;
+    }
+}
diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
index f5d822520a7..87c07279552 100644
--- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
+++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
@@ -4,6 +4,12 @@
   fn main() -> () {
       let mut _0: ();
       let _1: u8;
+      let mut _5: u8;
+      let mut _6: u8;
+      let mut _7: u8;
+      let mut _8: u8;
+      let mut _14: u32;
+      let mut _15: u32;
       scope 1 {
 -         debug x => _1;
 +         debug x => const 1_u8;
@@ -19,34 +25,23 @@
                   scope 4 {
 -                     debug sum => _4;
 +                     debug sum => const 6_u8;
-                      let _5: &str;
+                      let _9: &str;
                       scope 5 {
--                         debug s => _5;
+-                         debug s => _9;
 +                         debug s => const "hello, world!";
-                          let _8: bool;
-                          let _9: bool;
-                          let _10: u32;
+                          let _10: (bool, bool, u32);
                           scope 6 {
--                             debug ((f: (bool, bool, u32)).0: bool) => _8;
--                             debug ((f: (bool, bool, u32)).1: bool) => _9;
--                             debug ((f: (bool, bool, u32)).2: u32) => _10;
-+                             debug ((f: (bool, bool, u32)).0: bool) => const true;
-+                             debug ((f: (bool, bool, u32)).1: bool) => const false;
-+                             debug ((f: (bool, bool, u32)).2: u32) => const 123_u32;
-                              let _6: std::option::Option<u16>;
+                              debug f => _10;
+                              let _11: std::option::Option<u16>;
                               scope 7 {
--                                 debug o => _6;
-+                                 debug o => const Option::<u16>::Some(99_u16);
-                                  let _11: u32;
-                                  let _12: u32;
+                                  debug o => _11;
+                                  let _12: Point;
                                   scope 8 {
--                                     debug ((p: Point).0: u32) => _11;
--                                     debug ((p: Point).1: u32) => _12;
-+                                     debug ((p: Point).0: u32) => const 32_u32;
-+                                     debug ((p: Point).1: u32) => const 32_u32;
-                                      let _7: u32;
+-                                     debug p => _12;
++                                     debug p => const Point {{ x: 32_u32, y: 32_u32 }};
+                                      let _13: u32;
                                       scope 9 {
--                                         debug a => _7;
+-                                         debug a => _13;
 +                                         debug a => const 64_u32;
                                       }
                                   }
@@ -59,37 +54,57 @@
       }
   
       bb0: {
+          StorageLive(_1);
           _1 = const 1_u8;
+          StorageLive(_2);
           _2 = const 2_u8;
+          StorageLive(_3);
           _3 = const 3_u8;
           StorageLive(_4);
-          _4 = const 6_u8;
           StorageLive(_5);
-          _5 = const "hello, world!";
-          StorageLive(_8);
-          StorageLive(_9);
-          StorageLive(_10);
-          _8 = const true;
-          _9 = const false;
-          _10 = const 123_u32;
           StorageLive(_6);
-          _6 = const Option::<u16>::Some(99_u16);
-          _11 = const 32_u32;
-          _12 = const 32_u32;
+          _6 = const 1_u8;
           StorageLive(_7);
-          _7 = const 64_u32;
+          _7 = const 2_u8;
+          _5 = const 3_u8;
           StorageDead(_7);
           StorageDead(_6);
+          StorageLive(_8);
+          _8 = const 3_u8;
+          _4 = const 6_u8;
           StorageDead(_8);
-          StorageDead(_9);
-          StorageDead(_10);
           StorageDead(_5);
+          StorageLive(_9);
+          _9 = const "hello, world!";
+          StorageLive(_10);
+          _10 = (const true, const false, const 123_u32);
+          StorageLive(_11);
+          _11 = Option::<u16>::Some(const 99_u16);
+          StorageLive(_12);
+          _12 = const Point {{ x: 32_u32, y: 32_u32 }};
+          StorageLive(_13);
+          StorageLive(_14);
+          _14 = const 32_u32;
+          StorageLive(_15);
+          _15 = const 32_u32;
+          _13 = const 64_u32;
+          StorageDead(_15);
+          StorageDead(_14);
+          _0 = const ();
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageDead(_9);
           StorageDead(_4);
+          StorageDead(_3);
+          StorageDead(_2);
+          StorageDead(_1);
           return;
       }
   }
   
-  ALLOC0 (size: 4, align: 2) {
-      01 00 63 00                                     │ ..c.
+  ALLOC0 (size: 8, align: 4) {
+      20 00 00 00 20 00 00 00                         │  ... ...
   }
   
diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs
index d8ae08a0723..0e5ac4b8bd6 100644
--- a/tests/mir-opt/const_debuginfo.rs
+++ b/tests/mir-opt/const_debuginfo.rs
@@ -1,12 +1,23 @@
-// skip-filecheck
-// compile-flags: -C overflow-checks=no -Zunsound-mir-opts
+// unit-test: ConstDebugInfo
+// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+ConstProp
 
 struct Point {
     x: u32,
     y: u32,
 }
 
+// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => const 1_u8;
+    // CHECK: debug y => const 2_u8;
+    // CHECK: debug z => const 3_u8;
+    // CHECK: debug sum => const 6_u8;
+    // CHECK: debug s => const "hello, world!";
+    // CHECK: debug f => {{_.*}};
+    // CHECK: debug o => {{_.*}};
+    // CHECK: debug p => const Point
+    // CHECK: debug a => const 64_u32;
     let x = 1u8;
     let y = 2u8;
     let z = 3u8;
@@ -21,5 +32,3 @@ fn main() {
     let p = Point { x: 32, y: 32 };
     let a = p.x + p.y;
 }
-
-// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff
diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff
index 4eafb8d0917..4eafb8d0917 100644
--- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff
+++ b/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff
diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff
index 445d9895d6a..445d9895d6a 100644
--- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff
+++ b/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs
new file mode 100644
index 00000000000..ec9da6e8e5c
--- /dev/null
+++ b/tests/mir-opt/const_prop/indirect_mutation.rs
@@ -0,0 +1,41 @@
+// unit-test: ConstProp
+// Check that we do not propagate past an indirect mutation.
+#![feature(raw_ref_op)]
+
+// EMIT_MIR indirect_mutation.foo.ConstProp.diff
+fn foo() {
+    // CHECK-LABEL: fn foo(
+    // CHECK: debug u => _1;
+    // CHECK: debug y => _3;
+    // CHECK: _1 = (const 1_i32,);
+    // CHECK: _2 = &mut (_1.0: i32);
+    // CHECK: (*_2) = const 5_i32;
+    // CHECK: _4 = (_1.0: i32);
+    // CHECK: _3 = Eq(move _4, const 5_i32);
+
+    let mut u = (1,);
+    *&mut u.0 = 5;
+    let y = { u.0 } == 5;
+}
+
+// EMIT_MIR indirect_mutation.bar.ConstProp.diff
+fn bar() {
+    // CHECK-LABEL: fn bar(
+    // CHECK: debug v => _1;
+    // CHECK: debug y => _4;
+    // CHECK: _3 = &raw mut (_1.0: i32);
+    // CHECK: (*_3) = const 5_i32;
+    // CHECK: _5 = (_1.0: i32);
+    // CHECK: _4 = Eq(move _5, const 5_i32);
+
+    let mut v = (1,);
+    unsafe {
+        *&raw mut v.0 = 5;
+    }
+    let y = { v.0 } == 5;
+}
+
+fn main() {
+    foo();
+    bar();
+}
diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs
index 8a5289d5899..2571c3856f4 100644
--- a/tests/mir-opt/const_prop/offset_of.rs
+++ b/tests/mir-opt/const_prop/offset_of.rs
@@ -2,7 +2,7 @@
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-#![feature(offset_of)]
+#![feature(offset_of, offset_of_enum)]
 
 use std::marker::PhantomData;
 use std::mem::offset_of;
diff --git a/tests/mir-opt/const_prop_miscompile.rs b/tests/mir-opt/const_prop_miscompile.rs
deleted file mode 100644
index 00696535ac1..00000000000
--- a/tests/mir-opt/const_prop_miscompile.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// skip-filecheck
-// unit-test: ConstProp
-#![feature(raw_ref_op)]
-
-// EMIT_MIR const_prop_miscompile.foo.ConstProp.diff
-fn foo() {
-    let mut u = (1,);
-    *&mut u.0 = 5;
-    let y = { u.0 } == 5;
-}
-
-// EMIT_MIR const_prop_miscompile.bar.ConstProp.diff
-fn bar() {
-    let mut v = (1,);
-    unsafe {
-        *&raw mut v.0 = 5;
-    }
-    let y = { v.0 } == 5;
-}
-
-fn main() {
-    foo();
-    bar();
-}
diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs
deleted file mode 100644
index 3a3d451ee8d..00000000000
--- a/tests/mir-opt/while_storage.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-// Test that we correctly generate StorageDead statements for while loop
-// conditions on all branches
-
-fn get_bool(c: bool) -> bool {
-    c
-}
-
-// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir
-fn while_loop(c: bool) {
-    while get_bool(c) {
-        if get_bool(c) {
-            break;
-        }
-    }
-}
-
-fn main() {
-    while_loop(false);
-}
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir
deleted file mode 100644
index 21c4b92cf04..00000000000
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir
+++ /dev/null
@@ -1,16 +0,0 @@
-// MIR for `while_loop` after PreCodegen
-
-fn while_loop(_1: bool) -> () {
-    debug c => _1;
-    let mut _0: ();
-    scope 1 (inlined get_bool) {
-        debug c => _1;
-    }
-    scope 2 (inlined get_bool) {
-        debug c => _1;
-    }
-
-    bb0: {
-        return;
-    }
-}
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir
deleted file mode 100644
index 21c4b92cf04..00000000000
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir
+++ /dev/null
@@ -1,16 +0,0 @@
-// MIR for `while_loop` after PreCodegen
-
-fn while_loop(_1: bool) -> () {
-    debug c => _1;
-    let mut _0: ();
-    scope 1 (inlined get_bool) {
-        debug c => _1;
-    }
-    scope 2 (inlined get_bool) {
-        debug c => _1;
-    }
-
-    bb0: {
-        return;
-    }
-}
diff --git a/tests/run-coverage/abort.rs b/tests/run-coverage/abort.rs
deleted file mode 100644
index 98264bdc1af..00000000000
--- a/tests/run-coverage/abort.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-#![feature(c_unwind)]
-#![allow(unused_assignments)]
-
-extern "C" fn might_abort(should_abort: bool) {
-    if should_abort {
-        println!("aborting...");
-        panic!("panics and aborts");
-    } else {
-        println!("Don't Panic");
-    }
-}
-
-fn main() -> Result<(), u8> {
-    let mut countdown = 10;
-    while countdown > 0 {
-        if countdown < 5 {
-            might_abort(false);
-        }
-        // See discussion (below the `Notes` section) on coverage results for the closing brace.
-        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
-        // For the following example, the closing brace is the last character on the line.
-        // This shows the character after the closing brace is highlighted, even if that next
-        // character is a newline.
-        if countdown < 5 { might_abort(false); }
-        countdown -= 1;
-    }
-    Ok(())
-}
-
-// Notes:
-//   1. Compare this program and its coverage results to those of the similar tests
-//      `panic_unwind.rs` and `try_error_result.rs`.
-//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
-//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
-//      results show where the program did and did not execute.
-//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
-//      intended"). Coverage results would show no executed coverage regions.
-//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
-//      (on Linux at least).
-
-/*
-
-Expect the following coverage results:
-
-```text
-    16|     11|    while countdown > 0 {
-    17|     10|        if countdown < 5 {
-    18|      4|            might_abort(false);
-    19|      6|        }
-```
-
-This is actually correct.
-
-The condition `countdown < 5` executed 10 times (10 loop iterations).
-
-It evaluated to `true` 4 times, and executed the `might_abort()` call.
-
-It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
-`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
-closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
-non-true condition.
-
-As another example of why this is important, say the condition was `countdown < 50`, which is always
-`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
-The closing brace would have a count of `0`, highlighting the missed coverage.
-*/
diff --git a/tests/run-coverage/assert.rs b/tests/run-coverage/assert.rs
deleted file mode 100644
index 85e6662a6ad..00000000000
--- a/tests/run-coverage/assert.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 101
-
-fn might_fail_assert(one_plus_one: u32) {
-    println!("does 1 + 1 = {}?", one_plus_one);
-    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
-}
-
-fn main() -> Result<(), u8> {
-    let mut countdown = 10;
-    while countdown > 0 {
-        if countdown == 1 {
-            might_fail_assert(3);
-        } else if countdown < 5 {
-            might_fail_assert(2);
-        }
-        countdown -= 1;
-    }
-    Ok(())
-}
-
-// Notes:
-//   1. Compare this program and its coverage results to those of the very similar test
-//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
-//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
-//      related `assert_*!()` macro.
-//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
-//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
-//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
-//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
-//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
-//      Rust compiler to check for runtime failures, such as numeric overflows.
diff --git a/tests/run-coverage/async.rs b/tests/run-coverage/async.rs
deleted file mode 100644
index efd9e62d64e..00000000000
--- a/tests/run-coverage/async.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-#![allow(unused_assignments, dead_code)]
-
-// compile-flags: --edition=2018 -C opt-level=1
-
-async fn c(x: u8) -> u8 {
-    if x == 8 {
-        1
-    } else {
-        0
-    }
-}
-
-async fn d() -> u8 { 1 }
-
-async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
-
-async fn f() -> u8 { 1 }
-
-async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
-
-pub async fn g(x: u8) {
-    match x {
-        y if e().await == y => (),
-        y if f().await == y => (),
-        _ => (),
-    }
-}
-
-async fn h(x: usize) { // The function signature is counted when called, but the body is not
-                       // executed (not awaited) so the open brace has a `0` count (at least when
-                       // displayed with `llvm-cov show` in color-mode).
-    match x {
-        y if foo().await[y] => (),
-        _ => (),
-    }
-}
-
-async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
-                    // (a) the function signature, counted when the function is called; and
-                    // (b) the open brace for the function body, counted once when the body is
-                    // executed asynchronously.
-    match x {
-        y if c(x).await == y + 1 => { d().await; }
-        y if f().await == y + 1 => (),
-        _ => (),
-    }
-}
-
-fn j(x: u8) {
-    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
-    fn c(x: u8) -> u8 {
-        if x == 8 {
-            1 // This line appears covered, but the 1-character expression span covering the `1`
-              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
-              // `fn j()` executes the open brace for the function body, followed by the function's
-              // first executable statement, `match x`. Inner function declarations are not
-              // "visible" to the MIR for `j()`, so the code region counts all lines between the
-              // open brace and the first statement as executed, which is, in a sense, true.
-              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
-              // of the enclosed coverages, (that is, the `1` expression was not executed, and
-              // accurately displays a `0`).
-        } else {
-            0
-        }
-    }
-    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
-    fn f() -> u8 { 1 }
-    match x {
-        y if c(x) == y + 1 => { d(); }
-        y if f() == y + 1 => (),
-        _ => (),
-    }
-}
-
-fn k(x: u8) { // unused function
-    match x {
-        1 => (),
-        2 => (),
-        _ => (),
-    }
-}
-
-fn l(x: u8) {
-    match x {
-        1 => (),
-        2 => (),
-        _ => (),
-    }
-}
-
-async fn m(x: u8) -> u8 { x - 1 }
-
-fn main() {
-    let _ = g(10);
-    let _ = h(9);
-    let mut future = Box::pin(i(8));
-    j(7);
-    l(6);
-    let _ = m(5);
-    executor::block_on(future.as_mut());
-}
-
-mod executor {
-    use core::{
-        future::Future,
-        pin::Pin,
-        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-    };
-
-    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-        use std::hint::unreachable_unchecked;
-        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-            |_| unsafe { unreachable_unchecked() }, // clone
-            |_| unsafe { unreachable_unchecked() }, // wake
-            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-            |_| (),
-        );
-        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-        let mut context = Context::from_waker(&waker);
-
-        loop {
-            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-                break val;
-            }
-        }
-    }
-}
diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs
deleted file mode 100644
index 2884ff297af..00000000000
--- a/tests/run-coverage/async2.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-// compile-flags: --edition=2018
-
-fn non_async_func() {
-    println!("non_async_func was covered");
-    let b = true;
-    if b {
-        println!("non_async_func println in block");
-    }
-}
-
-async fn async_func() {
-    println!("async_func was covered");
-    let b = true;
-    if b {
-        println!("async_func println in block");
-    }
-}
-
-async fn async_func_just_println() {
-    println!("async_func_just_println was covered");
-}
-
-fn main() {
-    println!("codecovsample::main");
-
-    non_async_func();
-
-    executor::block_on(async_func());
-    executor::block_on(async_func_just_println());
-}
-
-mod executor {
-    use core::{
-        future::Future,
-        pin::Pin,
-        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-    };
-
-    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-        use std::hint::unreachable_unchecked;
-        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-            |_| unsafe { unreachable_unchecked() }, // clone
-            |_| unsafe { unreachable_unchecked() }, // wake
-            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-            |_| (),
-        );
-        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-        let mut context = Context::from_waker(&waker);
-
-        loop {
-            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-                break val;
-            }
-        }
-    }
-}
diff --git a/tests/run-coverage/bad_counter_ids.rs b/tests/run-coverage/bad_counter_ids.rs
deleted file mode 100644
index ef5460102b7..00000000000
--- a/tests/run-coverage/bad_counter_ids.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-#![feature(coverage_attribute)]
-// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3
-
-// Regression test for <https://github.com/rust-lang/rust/issues/117012>.
-//
-// If some coverage counters were removed by MIR optimizations, we need to take
-// care not to refer to those counter IDs in coverage mappings, and instead
-// replace them with a constant zero value. If we don't, `llvm-cov` might see
-// a too-large counter ID and silently discard the entire function from its
-// coverage reports.
-
-#[derive(Debug, PartialEq, Eq)]
-struct Foo(u32);
-
-fn eq_good() {
-    println!("a");
-    assert_eq!(Foo(1), Foo(1));
-}
-
-fn eq_good_message() {
-    println!("b");
-    assert_eq!(Foo(1), Foo(1), "message b");
-}
-
-fn ne_good() {
-    println!("c");
-    assert_ne!(Foo(1), Foo(3));
-}
-
-fn ne_good_message() {
-    println!("d");
-    assert_ne!(Foo(1), Foo(3), "message d");
-}
-
-fn eq_bad() {
-    println!("e");
-    assert_eq!(Foo(1), Foo(3));
-}
-
-fn eq_bad_message() {
-    println!("f");
-    assert_eq!(Foo(1), Foo(3), "message f");
-}
-
-fn ne_bad() {
-    println!("g");
-    assert_ne!(Foo(1), Foo(1));
-}
-
-fn ne_bad_message() {
-    println!("h");
-    assert_ne!(Foo(1), Foo(1), "message h");
-}
-
-#[coverage(off)]
-fn main() {
-    eq_good();
-    eq_good_message();
-    ne_good();
-    ne_good_message();
-
-    assert!(std::panic::catch_unwind(eq_bad).is_err());
-    assert!(std::panic::catch_unwind(eq_bad_message).is_err());
-    assert!(std::panic::catch_unwind(ne_bad).is_err());
-    assert!(std::panic::catch_unwind(ne_bad_message).is_err());
-}
diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs
deleted file mode 100644
index 16a2c4e33bd..00000000000
--- a/tests/run-coverage/closure.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=2
-
-// This test used to be sensitive to certain coverage-specific hacks in
-// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by
-// <https://github.com/rust-lang/rust/pull/83666>.
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-    let is_false = !is_true;
-
-    let mut some_string = Some(String::from("the string content"));
-    println!(
-        "The string or alt: {}"
-        ,
-        some_string
-            .
-            unwrap_or_else
-        (
-            ||
-            {
-                let mut countdown = 0;
-                if is_false {
-                    countdown = 10;
-                }
-                "alt string 1".to_owned()
-            }
-        )
-    );
-
-    some_string = Some(String::from("the string content"));
-    let
-        a
-    =
-        ||
-    {
-        let mut countdown = 0;
-        if is_false {
-            countdown = 10;
-        }
-        "alt string 2".to_owned()
-    };
-    println!(
-        "The string or alt: {}"
-        ,
-        some_string
-            .
-            unwrap_or_else
-        (
-            a
-        )
-    );
-
-    some_string = None;
-    println!(
-        "The string or alt: {}"
-        ,
-        some_string
-            .
-            unwrap_or_else
-        (
-            ||
-            {
-                let mut countdown = 0;
-                if is_false {
-                    countdown = 10;
-                }
-                "alt string 3".to_owned()
-            }
-        )
-    );
-
-    some_string = None;
-    let
-        a
-    =
-        ||
-    {
-        let mut countdown = 0;
-        if is_false {
-            countdown = 10;
-        }
-        "alt string 4".to_owned()
-    };
-    println!(
-        "The string or alt: {}"
-        ,
-        some_string
-            .
-            unwrap_or_else
-        (
-            a
-        )
-    );
-
-    let
-        quote_closure
-    =
-        |val|
-    {
-        let mut countdown = 0;
-        if is_false {
-            countdown = 10;
-        }
-        format!("'{}'", val)
-    };
-    println!(
-        "Repeated, quoted string: {:?}"
-        ,
-        std::iter::repeat("repeat me")
-            .take(5)
-            .map
-        (
-            quote_closure
-        )
-            .collect::<Vec<_>>()
-    );
-
-    let
-        _unused_closure
-    =
-        |
-            mut countdown
-        |
-    {
-        if is_false {
-            countdown = 10;
-        }
-        "closure should be unused".to_owned()
-    };
-
-    let mut countdown = 10;
-    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
-
-
-    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
-    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
-    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
-
-
-
-
-    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
-
-    let _shortish_unused_closure = | _unused_arg: u8 | {
-        println!("not called")
-    };
-
-    let _as_short_unused_closure = |
-        _unused_arg: u8
-    | { println!("not called") };
-
-    let _almost_as_short_unused_closure = |
-        _unused_arg: u8
-    | { println!("not called") }
-    ;
-
-
-
-
-
-    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
-println!("not called")
-    ;
-
-    let _short_unused_closure_line_break_no_block2 =
-        | _unused_arg: u8 |
-            println!(
-                "not called"
-            )
-    ;
-
-    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
-        | _unused_arg: u8 |
-            println!(
-                "not called: {}",
-                if is_true { "check" } else { "me" }
-            )
-    ;
-
-    let short_used_not_covered_closure_line_break_block_embedded_branch =
-        | _unused_arg: u8 |
-        {
-            println!(
-                "not called: {}",
-                if is_true { "check" } else { "me" }
-            )
-        }
-    ;
-
-    let short_used_covered_closure_line_break_no_block_embedded_branch =
-        | _unused_arg: u8 |
-            println!(
-                "not called: {}",
-                if is_true { "check" } else { "me" }
-            )
-    ;
-
-    let short_used_covered_closure_line_break_block_embedded_branch =
-        | _unused_arg: u8 |
-        {
-            println!(
-                "not called: {}",
-                if is_true { "check" } else { "me" }
-            )
-        }
-    ;
-
-    if is_false {
-        short_used_not_covered_closure_macro(0);
-        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
-        short_used_not_covered_closure_line_break_block_embedded_branch(0);
-    }
-    short_used_covered_closure_macro(0);
-    short_used_covered_closure_line_break_no_block_embedded_branch(0);
-    short_used_covered_closure_line_break_block_embedded_branch(0);
-}
diff --git a/tests/run-coverage/closure_bug.rs b/tests/run-coverage/closure_bug.rs
deleted file mode 100644
index 739bc5f0b51..00000000000
--- a/tests/run-coverage/closure_bug.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Regression test for #115930.
-// All of these closures are identical, and should produce identical output in
-// the coverage report. However, an unstable sort was causing them to be treated
-// inconsistently when preparing coverage spans.
-
-fn main() {
-    let truthy = std::env::args().len() == 1;
-
-    let a
-        =
-        |
-        |
-        if truthy { true } else { false };
-
-    a();
-    if truthy { a(); }
-
-    let b
-        =
-        |
-        |
-        if truthy { true } else { false };
-
-    b();
-    if truthy { b(); }
-
-    let c
-        =
-        |
-        |
-        if truthy { true } else { false };
-
-    c();
-    if truthy { c(); }
-
-    let d
-        =
-        |
-        |
-        if truthy { true } else { false };
-
-    d();
-    if truthy { d(); }
-}
diff --git a/tests/run-coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs
deleted file mode 100644
index 9b289141c2e..00000000000
--- a/tests/run-coverage/closure_macro.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// compile-flags: --edition=2018
-#![feature(coverage_attribute)]
-
-macro_rules! bail {
-    ($msg:literal $(,)?) => {
-        if $msg.len() > 0 {
-            println!("no msg");
-        } else {
-            println!($msg);
-        }
-        return Err(String::from($msg));
-    };
-}
-
-macro_rules! on_error {
-    ($value:expr, $error_message:expr) => {
-        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
-            let message = format!($error_message, e);
-            if message.len() > 0 {
-                println!("{}", message);
-                Ok(String::from("ok"))
-            } else {
-                bail!("error");
-            }
-        })
-    };
-}
-
-fn load_configuration_files() -> Result<String, String> {
-    Ok(String::from("config"))
-}
-
-pub fn main() -> Result<(), String> {
-    println!("Starting service");
-    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
-
-    let startup_delay_duration = String::from("arg");
-    let _ = (config, startup_delay_duration);
-    Ok(())
-}
diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs
deleted file mode 100644
index b4275599e59..00000000000
--- a/tests/run-coverage/closure_macro_async.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// compile-flags: --edition=2018
-#![feature(coverage_attribute)]
-
-macro_rules! bail {
-    ($msg:literal $(,)?) => {
-        if $msg.len() > 0 {
-            println!("no msg");
-        } else {
-            println!($msg);
-        }
-        return Err(String::from($msg));
-    };
-}
-
-macro_rules! on_error {
-    ($value:expr, $error_message:expr) => {
-        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
-            let message = format!($error_message, e);
-            if message.len() > 0 {
-                println!("{}", message);
-                Ok(String::from("ok"))
-            } else {
-                bail!("error");
-            }
-        })
-    };
-}
-
-fn load_configuration_files() -> Result<String, String> {
-    Ok(String::from("config"))
-}
-
-pub async fn test() -> Result<(), String> {
-    println!("Starting service");
-    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
-
-    let startup_delay_duration = String::from("arg");
-    let _ = (config, startup_delay_duration);
-    Ok(())
-}
-
-#[coverage(off)]
-fn main() {
-    executor::block_on(test()).unwrap();
-}
-
-mod executor {
-    use core::{
-        future::Future,
-        pin::Pin,
-        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-    };
-
-    #[coverage(off)]
-    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-        use std::hint::unreachable_unchecked;
-        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-            #[coverage(off)]
-            |_| unsafe { unreachable_unchecked() }, // clone
-            #[coverage(off)]
-            |_| unsafe { unreachable_unchecked() }, // wake
-            #[coverage(off)]
-            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-            #[coverage(off)]
-            |_| (),
-        );
-        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-        let mut context = Context::from_waker(&waker);
-
-        loop {
-            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-                break val;
-            }
-        }
-    }
-}
diff --git a/tests/run-coverage/conditions.rs b/tests/run-coverage/conditions.rs
deleted file mode 100644
index fa7f2a116c2..00000000000
--- a/tests/run-coverage/conditions.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    let mut countdown = 0;
-    if true {
-        countdown = 10;
-    }
-
-    const B: u32 = 100;
-    let x = if countdown > 7 {
-        countdown -= 4;
-        B
-    } else if countdown > 2 {
-        if countdown < 1 || countdown > 5 || countdown != 9 {
-            countdown = 0;
-        }
-        countdown -= 5;
-        countdown
-    } else {
-        return;
-    };
-
-    let mut countdown = 0;
-    if true {
-        countdown = 10;
-    }
-
-    if countdown > 7 {
-        countdown -= 4;
-    } else if countdown > 2 {
-        if countdown < 1 || countdown > 5 || countdown != 9 {
-            countdown = 0;
-        }
-        countdown -= 5;
-    } else {
-        return;
-    }
-
-    if true {
-        let mut countdown = 0;
-        if true {
-            countdown = 10;
-        }
-
-        if countdown > 7 {
-            countdown -= 4;
-        }
-        else if countdown > 2 {
-            if countdown < 1 || countdown > 5 || countdown != 9 {
-                countdown = 0;
-            }
-            countdown -= 5;
-        } else {
-            return;
-        }
-    }
-
-    let mut countdown = 0;
-    if true {
-        countdown = 1;
-    }
-
-    let z = if countdown > 7 {
-        countdown -= 4;
-    } else if countdown > 2 {
-        if countdown < 1 || countdown > 5 || countdown != 9 {
-            countdown = 0;
-        }
-        countdown -= 5;
-    } else {
-        let should_be_reachable = countdown;
-        println!("reached");
-        return;
-    };
-
-    let w = if countdown > 7 {
-        countdown -= 4;
-    } else if countdown > 2 {
-        if countdown < 1 || countdown > 5 || countdown != 9 {
-            countdown = 0;
-        }
-        countdown -= 5;
-    } else {
-        return;
-    };
-}
diff --git a/tests/run-coverage/continue.rs b/tests/run-coverage/continue.rs
deleted file mode 100644
index 624aa98341b..00000000000
--- a/tests/run-coverage/continue.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    let is_true = std::env::args().len() == 1;
-
-    let mut x = 0;
-    for _ in 0..10 {
-        match is_true {
-            true => {
-                continue;
-            }
-            _ => {
-                x = 1;
-            }
-        }
-        x = 3;
-    }
-    for _ in 0..10 {
-        match is_true {
-            false => {
-                x = 1;
-            }
-            _ => {
-                continue;
-            }
-        }
-        x = 3;
-    }
-    for _ in 0..10 {
-        match is_true {
-            true => {
-                x = 1;
-            }
-            _ => {
-                continue;
-            }
-        }
-        x = 3;
-    }
-    for _ in 0..10 {
-        if is_true {
-            continue;
-        }
-        x = 3;
-    }
-    for _ in 0..10 {
-        match is_true {
-            false => {
-                x = 1;
-            }
-            _ => {
-                let _ = x;
-            }
-        }
-        x = 3;
-    }
-    for _ in 0..10 {
-        match is_true {
-            false => {
-                x = 1;
-            }
-            _ => {
-                break;
-            }
-        }
-        x = 3;
-    }
-    let _ = x;
-}
diff --git a/tests/run-coverage/coroutine.rs b/tests/run-coverage/coroutine.rs
deleted file mode 100644
index 86d19af6f4f..00000000000
--- a/tests/run-coverage/coroutine.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![feature(coroutines, coroutine_trait)]
-
-use std::ops::{Coroutine, CoroutineState};
-use std::pin::Pin;
-
-// The following implementation of a function called from a `yield` statement
-// (apparently requiring the Result and the `String` type or constructor)
-// creates conditions where the `coroutine::StateTransform` MIR transform will
-// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
-// to handle this condition, and still report dead block coverage.
-fn get_u32(val: bool) -> Result<u32, String> {
-    if val { Ok(1) } else { Err(String::from("some error")) }
-}
-
-fn main() {
-    let is_true = std::env::args().len() == 1;
-    let mut coroutine = || {
-        yield get_u32(is_true);
-        return "foo";
-    };
-
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Yielded(Ok(1)) => {}
-        _ => panic!("unexpected return from resume"),
-    }
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Complete("foo") => {}
-        _ => panic!("unexpected return from resume"),
-    }
-}
diff --git a/tests/run-coverage/dead_code.rs b/tests/run-coverage/dead_code.rs
deleted file mode 100644
index 3492712a6f9..00000000000
--- a/tests/run-coverage/dead_code.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![allow(dead_code, unused_assignments, unused_variables)]
-
-pub fn unused_pub_fn_not_in_library() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-    if is_true {
-        countdown = 10;
-    }
-}
-
-fn unused_fn() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-    if is_true {
-        countdown = 10;
-    }
-}
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-    if is_true {
-        countdown = 10;
-    }
-}
diff --git a/tests/run-coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs
deleted file mode 100644
index 7b062719c6b..00000000000
--- a/tests/run-coverage/drop_trait.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 1
-
-struct Firework {
-    strength: i32,
-}
-
-impl Drop for Firework {
-    fn drop(&mut self) {
-        println!("BOOM times {}!!!", self.strength);
-    }
-}
-
-fn main() -> Result<(), u8> {
-    let _firecracker = Firework { strength: 1 };
-
-    let _tnt = Firework { strength: 100 };
-
-    if true {
-        println!("Exiting with error...");
-        return Err(1);
-    }
-
-    let _ = Firework { strength: 1000 };
-
-    Ok(())
-}
-
-// Expected program output:
-//   Exiting with error...
-//   BOOM times 100!!!
-//   BOOM times 1!!!
-//   Error: 1
diff --git a/tests/run-coverage/fn_sig_into_try.rs b/tests/run-coverage/fn_sig_into_try.rs
deleted file mode 100644
index 92850c8a188..00000000000
--- a/tests/run-coverage/fn_sig_into_try.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-#![feature(coverage_attribute)]
-// compile-flags: --edition=2021
-
-// Regression test for inconsistent handling of function signature spans that
-// are followed by code using the `?` operator.
-//
-// For each of these similar functions, the line containing the function
-// signature should be handled in the same way.
-
-fn a() -> Option<i32>
-{
-    Some(7i32);
-    Some(0)
-}
-
-fn b() -> Option<i32>
-{
-    Some(7i32)?;
-    Some(0)
-}
-
-fn c() -> Option<i32>
-{
-    let _ = Some(7i32)?;
-    Some(0)
-}
-
-fn d() -> Option<i32>
-{
-    let _: () = ();
-    Some(7i32)?;
-    Some(0)
-}
-
-#[coverage(off)]
-fn main() {
-    a();
-    b();
-    c();
-    d();
-}
diff --git a/tests/run-coverage/generics.rs b/tests/run-coverage/generics.rs
deleted file mode 100644
index bf4c2d8d685..00000000000
--- a/tests/run-coverage/generics.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 1
-
-struct Firework<T> where T: Copy + std::fmt::Display {
-    strength: T,
-}
-
-impl<T> Firework<T> where T: Copy + std::fmt::Display {
-    #[inline(always)]
-    fn set_strength(&mut self, new_strength: T) {
-        self.strength = new_strength;
-    }
-}
-
-impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
-    #[inline(always)]
-    fn drop(&mut self) {
-        println!("BOOM times {}!!!", self.strength);
-    }
-}
-
-fn main() -> Result<(), u8> {
-    let mut firecracker = Firework { strength: 1 };
-    firecracker.set_strength(2);
-
-    let mut tnt = Firework { strength: 100.1 };
-    tnt.set_strength(200.1);
-    tnt.set_strength(300.3);
-
-    if true {
-        println!("Exiting with error...");
-        return Err(1);
-    }
-
-    let _ = Firework { strength: 1000 };
-
-    Ok(())
-}
-
-// Expected program output:
-//   Exiting with error...
-//   BOOM times 100!!!
-//   BOOM times 1!!!
-//   Error: 1
diff --git a/tests/run-coverage/if.rs b/tests/run-coverage/if.rs
deleted file mode 100644
index 8ad5042ff7b..00000000000
--- a/tests/run-coverage/if.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let
-    is_true
-    =
-        std::env::args().len()
-    ==
-        1
-    ;
-    let
-        mut
-    countdown
-    =
-        0
-    ;
-    if
-        is_true
-    {
-        countdown
-        =
-            10
-        ;
-    }
-}
diff --git a/tests/run-coverage/if_else.rs b/tests/run-coverage/if_else.rs
deleted file mode 100644
index 3244e1e3afd..00000000000
--- a/tests/run-coverage/if_else.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-    if
-        is_true
-    {
-        countdown
-        =
-            10
-        ;
-    }
-    else // Note coverage region difference without semicolon
-    {
-        countdown
-        =
-            100
-    }
-
-    if
-        is_true
-    {
-        countdown
-        =
-            10
-        ;
-    }
-    else
-    {
-        countdown
-        =
-            100
-        ;
-    }
-}
diff --git a/tests/run-coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs
deleted file mode 100644
index 854fa062967..00000000000
--- a/tests/run-coverage/inline-dead.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Regression test for issue #98833.
-// compile-flags: -Zinline-mir -Cdebug-assertions=off
-
-fn main() {
-    println!("{}", live::<false>());
-
-    let f = |x: bool| {
-        debug_assert!(
-            x
-        );
-    };
-    f(false);
-}
-
-#[inline]
-fn live<const B: bool>() -> u32 {
-    if B {
-        dead()
-    } else {
-        0
-    }
-}
-
-#[inline]
-fn dead() -> u32 {
-    42
-}
diff --git a/tests/run-coverage/inline.rs b/tests/run-coverage/inline.rs
deleted file mode 100644
index 9cfab9ddbad..00000000000
--- a/tests/run-coverage/inline.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// compile-flags: -Zinline-mir
-
-use std::fmt::Display;
-
-fn main() {
-    permutations(&['a', 'b', 'c']);
-}
-
-#[inline(always)]
-fn permutations<T: Copy + Display>(xs: &[T]) {
-    let mut ys = xs.to_owned();
-    permutate(&mut ys, 0);
-}
-
-fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
-    let n = length(xs);
-    if k == n {
-        display(xs);
-    } else if k < n {
-        for i in k..n {
-            swap(xs, i, k);
-            permutate(xs, k + 1);
-            swap(xs, i, k);
-        }
-    } else {
-        error();
-    }
-}
-
-fn length<T>(xs: &[T]) -> usize {
-    xs.len()
-}
-
-#[inline]
-fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
-    let t = xs[i];
-    xs[i] = xs[j];
-    xs[j] = t;
-}
-
-fn display<T: Display>(xs: &[T]) {
-    for x in xs {
-        print!("{}", x);
-    }
-    println!();
-}
-
-#[inline(always)]
-fn error() {
-    panic!("error");
-}
diff --git a/tests/run-coverage/inner_items.rs b/tests/run-coverage/inner_items.rs
deleted file mode 100644
index bcb62b3031c..00000000000
--- a/tests/run-coverage/inner_items.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-#![allow(unused_assignments, unused_variables, dead_code)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-    if is_true {
-        countdown = 10;
-    }
-
-    mod in_mod {
-        const IN_MOD_CONST: u32 = 1000;
-    }
-
-    fn in_func(a: u32) {
-        let b = 1;
-        let c = a + b;
-        println!("c = {}", c)
-    }
-
-    struct InStruct {
-        in_struct_field: u32,
-    }
-
-    const IN_CONST: u32 = 1234;
-
-    trait InTrait {
-        fn trait_func(&mut self, incr: u32);
-
-        fn default_trait_func(&mut self) {
-            in_func(IN_CONST);
-            self.trait_func(IN_CONST);
-        }
-    }
-
-    impl InTrait for InStruct {
-        fn trait_func(&mut self, incr: u32) {
-            self.in_struct_field += incr;
-            in_func(self.in_struct_field);
-        }
-    }
-
-    type InType = String;
-
-    if is_true {
-        in_func(countdown);
-    }
-
-    let mut val = InStruct {
-        in_struct_field: 101,
-    };
-
-    val.default_trait_func();
-}
diff --git a/tests/run-coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs
deleted file mode 100644
index 0b72a81947c..00000000000
--- a/tests/run-coverage/issue-83601.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Shows that rust-lang/rust/83601 is resolved
-
-#[derive(Debug, PartialEq, Eq)]
-struct Foo(u32);
-
-fn main() {
-    let bar = Foo(1);
-    assert_eq!(bar, Foo(1));
-    let baz = Foo(0);
-    assert_ne!(baz, Foo(1));
-    println!("{:?}", Foo(1));
-    println!("{:?}", bar);
-    println!("{:?}", baz);
-}
diff --git a/tests/run-coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs
deleted file mode 100644
index facf5b5b4cf..00000000000
--- a/tests/run-coverage/issue-84561.rs
+++ /dev/null
@@ -1,182 +0,0 @@
-// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
-
-// failure-status: 101
-#[derive(PartialEq, Eq)]
-struct Foo(u32);
-fn test3() {
-    let is_true = std::env::args().len() == 1;
-    let bar = Foo(1);
-    assert_eq!(bar, Foo(1));
-    let baz = Foo(0);
-    assert_ne!(baz, Foo(1));
-    println!("{:?}", Foo(1));
-    println!("{:?}", bar);
-    println!("{:?}", baz);
-
-    assert_eq!(Foo(1), Foo(1));
-    assert_ne!(Foo(0), Foo(1));
-    assert_eq!(Foo(2), Foo(2));
-    let bar = Foo(0);
-    assert_ne!(bar, Foo(3));
-    assert_ne!(Foo(0), Foo(4));
-    assert_eq!(Foo(3), Foo(3), "with a message");
-    println!("{:?}", bar);
-    println!("{:?}", Foo(1));
-
-    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
-    assert_ne!(
-        Foo(0)
-        ,
-        Foo(5)
-        ,
-        "{}"
-        ,
-        if
-        is_true
-        {
-            "true message"
-        } else {
-            "false message"
-        }
-    );
-
-    let is_true = std::env::args().len() == 1;
-
-    assert_eq!(
-        Foo(1),
-        Foo(1)
-    );
-    assert_ne!(
-        Foo(0),
-        Foo(1)
-    );
-    assert_eq!(
-        Foo(2),
-        Foo(2)
-    );
-    let bar = Foo(1);
-    assert_ne!(
-        bar,
-        Foo(3)
-    );
-    if is_true {
-        assert_ne!(
-            Foo(0),
-            Foo(4)
-        );
-    } else {
-        assert_eq!(
-            Foo(3),
-            Foo(3)
-        );
-    }
-    if is_true {
-        assert_ne!(
-            Foo(0),
-            Foo(4),
-            "with a message"
-        );
-    } else {
-        assert_eq!(
-            Foo(3),
-            Foo(3),
-            "with a message"
-        );
-    }
-    assert_ne!(
-        if is_true {
-            Foo(0)
-        } else {
-            Foo(1)
-        },
-        Foo(5)
-    );
-    assert_ne!(
-        Foo(5),
-        if is_true {
-            Foo(0)
-        } else {
-            Foo(1)
-        }
-    );
-    assert_ne!(
-        if is_true {
-            assert_eq!(
-                Foo(3),
-                Foo(3)
-            );
-            Foo(0)
-        } else {
-            assert_ne!(
-                if is_true {
-                    Foo(0)
-                } else {
-                    Foo(1)
-                },
-                Foo(5)
-            );
-            Foo(1)
-        },
-        Foo(5),
-        "with a message"
-    );
-    assert_eq!(
-        Foo(1),
-        Foo(3),
-        "this assert should fail"
-    );
-    assert_eq!(
-        Foo(3),
-        Foo(3),
-        "this assert should not be reached"
-    );
-}
-
-impl std::fmt::Debug for Foo {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        write!(f, "try and succeed")?;
-        Ok(())
-    }
-}
-
-static mut DEBUG_LEVEL_ENABLED: bool = false;
-
-macro_rules! debug {
-    ($($arg:tt)+) => (
-        if unsafe { DEBUG_LEVEL_ENABLED } {
-            println!($($arg)+);
-        }
-    );
-}
-
-fn test1() {
-    debug!("debug is enabled");
-    debug!("debug is enabled");
-    let _ = 0;
-    debug!("debug is enabled");
-    unsafe {
-        DEBUG_LEVEL_ENABLED = true;
-    }
-    debug!("debug is enabled");
-}
-
-macro_rules! call_debug {
-    ($($arg:tt)+) => (
-        fn call_print(s: &str) {
-            print!("{}", s);
-        }
-
-        call_print("called from call_debug: ");
-        debug!($($arg)+);
-    );
-}
-
-fn test2() {
-    call_debug!("debug is enabled");
-}
-
-fn main() {
-    test1();
-    test2();
-    test3();
-}
diff --git a/tests/run-coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs
deleted file mode 100644
index da546cfeef8..00000000000
--- a/tests/run-coverage/issue-93054.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![allow(dead_code, unreachable_code)]
-
-// Regression test for #93054: Functions using uninhabited types often only have a single,
-// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
-// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
-
-// compile-flags: --edition=2021
-
-enum Never {}
-
-impl Never {
-    fn foo(self) {
-        match self {}
-        make().map(|never| match never {});
-    }
-
-    fn bar(&self) {
-        match *self {}
-    }
-}
-
-async fn foo2(never: Never) {
-    match never {}
-}
-
-fn make() -> Option<Never> {
-    None
-}
-
-fn main() {}
diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs
deleted file mode 100644
index bb6219e851c..00000000000
--- a/tests/run-coverage/lazy_boolean.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let (mut a, mut b, mut c) = (0, 0, 0);
-    if is_true {
-        a = 1;
-        b = 10;
-        c = 100;
-    }
-    let
-        somebool
-        =
-            a < b
-        ||
-            b < c
-    ;
-    let
-        somebool
-        =
-            b < a
-        ||
-            b < c
-    ;
-    let somebool = a < b && b < c;
-    let somebool = b < a && b < c;
-
-    if
-        !
-        is_true
-    {
-        a = 2
-        ;
-    }
-
-    if
-        is_true
-    {
-        b = 30
-        ;
-    }
-    else
-    {
-        c = 400
-        ;
-    }
-
-    if !is_true {
-        a = 2;
-    }
-
-    if is_true {
-        b = 30;
-    } else {
-        c = 400;
-    }
-}
diff --git a/tests/run-coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs
deleted file mode 100644
index dbc4fad7a23..00000000000
--- a/tests/run-coverage/loop_break_value.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    let result
-        =
-            loop
-        {
-            break
-            10
-            ;
-        }
-    ;
-}
diff --git a/tests/run-coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs
deleted file mode 100644
index f3a343bcc1f..00000000000
--- a/tests/run-coverage/loops_branches.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-#![allow(unused_assignments, unused_variables, while_true)]
-
-// This test confirms that (1) unexecuted infinite loops are handled correctly by the
-// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
-
-struct DebugTest;
-
-impl std::fmt::Debug for DebugTest {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        if true {
-            if false {
-                while true {}
-            }
-            write!(f, "cool")?;
-        } else {
-        }
-
-        for i in 0..10 {
-            if true {
-                if false {
-                    while true {}
-                }
-                write!(f, "cool")?;
-            } else {
-            }
-        }
-        Ok(())
-    }
-}
-
-struct DisplayTest;
-
-impl std::fmt::Display for DisplayTest {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        if false {
-        } else {
-            if false {
-                while true {}
-            }
-            write!(f, "cool")?;
-        }
-        for i in 0..10 {
-            if false {
-            } else {
-                if false {
-                    while true {}
-                }
-                write!(f, "cool")?;
-            }
-        }
-        Ok(())
-    }
-}
-
-fn main() {
-    let debug_test = DebugTest;
-    println!("{:?}", debug_test);
-    let display_test = DisplayTest;
-    println!("{}", display_test);
-}
diff --git a/tests/run-coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs
deleted file mode 100644
index ab7aee51d1b..00000000000
--- a/tests/run-coverage/match_or_pattern.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut a: u8 = 0;
-    let mut b: u8 = 0;
-    if is_true {
-        a = 2;
-        b = 0;
-    }
-    match (a, b) {
-        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
-        // This test confirms a fix for Issue #79569.
-        (0 | 1, 2 | 3) => {}
-        _ => {}
-    }
-    if is_true {
-        a = 0;
-        b = 0;
-    }
-    match (a, b) {
-        (0 | 1, 2 | 3) => {}
-        _ => {}
-    }
-    if is_true {
-        a = 2;
-        b = 2;
-    }
-    match (a, b) {
-        (0 | 1, 2 | 3) => {}
-        _ => {}
-    }
-    if is_true {
-        a = 0;
-        b = 2;
-    }
-    match (a, b) {
-        (0 | 1, 2 | 3) => {}
-        _ => {}
-    }
-}
diff --git a/tests/run-coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs
deleted file mode 100644
index 4c7c7842796..00000000000
--- a/tests/run-coverage/nested_loops.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-fn main() {
-    let is_true = std::env::args().len() == 1;
-    let mut countdown = 10;
-
-    'outer: while countdown > 0 {
-        let mut a = 100;
-        let mut b = 100;
-        for _ in 0..50 {
-            if a < 30 {
-                break;
-            }
-            a -= 5;
-            b -= 5;
-            if b < 90 {
-                a -= 10;
-                if is_true {
-                    break 'outer;
-                } else {
-                    a -= 2;
-                }
-            }
-        }
-        countdown -= 1;
-    }
-}
diff --git a/tests/run-coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs
deleted file mode 100644
index e12e4bc55e3..00000000000
--- a/tests/run-coverage/no_cov_crate.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// Enables `coverage(off)` on the entire crate
-#![feature(coverage_attribute)]
-
-#[coverage(off)]
-fn do_not_add_coverage_1() {
-    println!("called but not covered");
-}
-
-fn do_not_add_coverage_2() {
-    #![coverage(off)]
-    println!("called but not covered");
-}
-
-#[coverage(off)]
-#[allow(dead_code)]
-fn do_not_add_coverage_not_called() {
-    println!("not called and not covered");
-}
-
-fn add_coverage_1() {
-    println!("called and covered");
-}
-
-fn add_coverage_2() {
-    println!("called and covered");
-}
-
-#[allow(dead_code)]
-fn add_coverage_not_called() {
-    println!("not called but covered");
-}
-
-// FIXME: These test-cases illustrate confusing results of nested functions.
-// See https://github.com/rust-lang/rust/issues/93319
-mod nested_fns {
-    #[coverage(off)]
-    pub fn outer_not_covered(is_true: bool) {
-        fn inner(is_true: bool) {
-            if is_true {
-                println!("called and covered");
-            } else {
-                println!("absolutely not covered");
-            }
-        }
-        println!("called but not covered");
-        inner(is_true);
-    }
-
-    pub fn outer(is_true: bool) {
-        println!("called and covered");
-        inner_not_covered(is_true);
-
-        #[coverage(off)]
-        fn inner_not_covered(is_true: bool) {
-            if is_true {
-                println!("called but not covered");
-            } else {
-                println!("absolutely not covered");
-            }
-        }
-    }
-
-    pub fn outer_both_covered(is_true: bool) {
-        println!("called and covered");
-        inner(is_true);
-
-        fn inner(is_true: bool) {
-            if is_true {
-                println!("called and covered");
-            } else {
-                println!("absolutely not covered");
-            }
-        }
-    }
-}
-
-fn main() {
-    let is_true = std::env::args().len() == 1;
-
-    do_not_add_coverage_1();
-    do_not_add_coverage_2();
-    add_coverage_1();
-    add_coverage_2();
-
-    nested_fns::outer_not_covered(is_true);
-    nested_fns::outer(is_true);
-    nested_fns::outer_both_covered(is_true);
-}
diff --git a/tests/run-coverage/overflow.rs b/tests/run-coverage/overflow.rs
deleted file mode 100644
index bbb65c1b35d..00000000000
--- a/tests/run-coverage/overflow.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 101
-
-fn might_overflow(to_add: u32) -> u32 {
-    if to_add > 5 {
-        println!("this will probably overflow");
-    }
-    let add_to = u32::MAX - 5;
-    println!("does {} + {} overflow?", add_to, to_add);
-    let result = to_add + add_to;
-    println!("continuing after overflow check");
-    result
-}
-
-fn main() -> Result<(), u8> {
-    let mut countdown = 10;
-    while countdown > 0 {
-        if countdown == 1 {
-            let result = might_overflow(10);
-            println!("Result: {}", result);
-        } else if countdown < 5 {
-            let result = might_overflow(1);
-            println!("Result: {}", result);
-        }
-        countdown -= 1;
-    }
-    Ok(())
-}
-
-// Notes:
-//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
-//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
-//   2. This test confirms the coverage generated when a program passes or fails a
-//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
-//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
-//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
-//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
-//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
-//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
-//      get its own coverage counter.
-//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
-//      In this test, the final count for the statements after the `if` block in `might_overflow()`
-//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
-//      on the MIR graph and the structure of the code, this count could have been 3 (which might
-//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
-//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
-//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
-//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
-//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
-//      executed, and counted, 4 times, before reaching the overflow add.
-
-// If the program did not overflow, the coverage for `might_overflow()` would look like this:
-//
-//     4|       |fn might_overflow(to_add: u32) -> u32 {
-//     5|      4|    if to_add > 5 {
-//     6|      0|        println!("this will probably overflow");
-//     7|      4|    }
-//     8|      4|    let add_to = u32::MAX - 5;
-//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
-//    10|      4|    let result = to_add + add_to;
-//    11|      4|    println!("continuing after overflow check");
-//    12|      4|    result
-//    13|      4|}
diff --git a/tests/run-coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs
deleted file mode 100644
index 638d2eb6aaa..00000000000
--- a/tests/run-coverage/panic_unwind.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 101
-
-fn might_panic(should_panic: bool) {
-    if should_panic {
-        println!("panicking...");
-        panic!("panics");
-    } else {
-        println!("Don't Panic");
-    }
-}
-
-fn main() -> Result<(), u8> {
-    let mut countdown = 10;
-    while countdown > 0 {
-        if countdown == 1 {
-            might_panic(true);
-        } else if countdown < 5 {
-            might_panic(false);
-        }
-        countdown -= 1;
-    }
-    Ok(())
-}
-
-// Notes:
-//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
-//      `try_error_result.rs`.
-//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
-//      normal program exit cleanup, including writing out the current values of the coverage
-//      counters.
diff --git a/tests/run-coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs
deleted file mode 100644
index dd8b42c18ce..00000000000
--- a/tests/run-coverage/partial_eq.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
-// structure of this test.
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Version {
-    major: usize,
-    minor: usize,
-    patch: usize,
-}
-
-impl Version {
-    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
-        Self {
-            major,
-            minor,
-            patch,
-        }
-    }
-}
-
-fn main() {
-    let version_3_2_1 = Version::new(3, 2, 1);
-    let version_3_3_0 = Version::new(3, 3, 0);
-
-    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
-}
-
-/*
-
-This test verifies a bug was fixed that otherwise generated this error:
-
-thread 'rustc' panicked at 'No counters provided the source_hash for function:
-    Instance {
-        def: Item(WithOptConstParam {
-            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
-            const_param_did: None
-        }),
-        args: []
-    }'
-The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
-without a code region associated with any `Counter`. Code regions were associated with at least
-one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
-(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
-`function_source_hash` without a code region, if necessary.
-
-*/
diff --git a/tests/run-coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs
deleted file mode 100644
index 6f7f23475b8..00000000000
--- a/tests/run-coverage/simple_loop.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-#![allow(unused_assignments)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 0;
-
-    if
-        is_true
-    {
-        countdown
-        =
-            10
-        ;
-    }
-
-    loop
-    {
-        if
-            countdown
-                ==
-            0
-        {
-            break
-            ;
-        }
-        countdown
-        -=
-        1
-        ;
-    }
-}
diff --git a/tests/run-coverage/simple_match.rs b/tests/run-coverage/simple_match.rs
deleted file mode 100644
index be99e59a826..00000000000
--- a/tests/run-coverage/simple_match.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
-    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    // dependent conditions.
-    let is_true = std::env::args().len() == 1;
-
-    let mut countdown = 1;
-    if is_true {
-        countdown = 0;
-    }
-
-    for
-        _
-    in
-        0..2
-    {
-        let z
-        ;
-        match
-            countdown
-        {
-            x
-            if
-                x
-                    <
-                1
-            =>
-            {
-                z = countdown
-                ;
-                let y = countdown
-                ;
-                countdown = 10
-                ;
-            }
-            _
-            =>
-            {}
-        }
-    }
-}
diff --git a/tests/run-coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs
deleted file mode 100644
index f89f9f3ec61..00000000000
--- a/tests/run-coverage/sort_groups.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// compile-flags: --edition=2021
-
-// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
-// predictable order, while preserving their heterogeneous contents.
-
-fn main() {
-    let cond = std::env::args().len() > 1;
-    generic_fn::<()>(cond);
-    generic_fn::<&'static str>(!cond);
-    if false {
-        generic_fn::<char>(cond);
-    }
-    generic_fn::<i32>(cond);
-    other_fn();
-}
-
-fn generic_fn<T>(cond: bool) {
-    if cond {
-        println!("{}", std::any::type_name::<T>());
-    }
-}
-
-fn other_fn() {}
diff --git a/tests/run-coverage/test_harness.rs b/tests/run-coverage/test_harness.rs
deleted file mode 100644
index 12a755734c1..00000000000
--- a/tests/run-coverage/test_harness.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Verify that the entry point injected by the test harness doesn't cause
-// weird artifacts in the coverage report (e.g. issue #10749).
-
-// compile-flags: --test
-
-#[allow(dead_code)]
-fn unused() {}
-
-#[test]
-fn my_test() {}
diff --git a/tests/run-coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs
deleted file mode 100644
index cef99027aaa..00000000000
--- a/tests/run-coverage/tight_inf_loop.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    if false {
-        loop {}
-    }
-}
diff --git a/tests/run-coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs
deleted file mode 100644
index 557cbf22bfa..00000000000
--- a/tests/run-coverage/try_error_result.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 1
-
-fn call(return_error: bool) -> Result<(), ()> {
-    if return_error {
-        Err(())
-    } else {
-        Ok(())
-    }
-}
-
-fn test1() -> Result<(), ()> {
-    let mut
-        countdown = 10
-    ;
-    for
-        _
-    in
-        0..10
-    {
-        countdown
-            -= 1
-        ;
-        if
-            countdown < 5
-        {
-            call(/*return_error=*/ true)?;
-            call(/*return_error=*/ false)?;
-        }
-        else
-        {
-            call(/*return_error=*/ false)?;
-        }
-    }
-    Ok(())
-}
-
-struct Thing1;
-impl Thing1 {
-    fn get_thing_2(&self, return_error: bool) -> Result<Thing2, ()> {
-        if return_error {
-            Err(())
-        } else {
-            Ok(Thing2 {})
-        }
-    }
-}
-
-struct Thing2;
-impl Thing2 {
-    fn call(&self, return_error: bool) -> Result<u32, ()> {
-        if return_error {
-            Err(())
-        } else {
-            Ok(57)
-        }
-    }
-}
-
-fn test2() -> Result<(), ()> {
-    let thing1 = Thing1{};
-    let mut
-        countdown = 10
-    ;
-    for
-        _
-    in
-        0..10
-    {
-        countdown
-            -= 1
-        ;
-        if
-            countdown < 5
-        {
-            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
-            thing1
-                .
-                get_thing_2(/*return_error=*/ false)
-                ?
-                .
-                call(/*return_error=*/ true)
-                .
-                expect_err(
-                    "call should fail"
-                );
-            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
-            assert_eq!(val, 57);
-            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
-            assert_eq!(val, 57);
-        }
-        else
-        {
-            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
-            assert_eq!(val, 57);
-            let val = thing1
-                .get_thing_2(/*return_error=*/ false)?
-                .call(/*return_error=*/ false)?;
-            assert_eq!(val, 57);
-            let val = thing1
-                .get_thing_2(/*return_error=*/ false)
-                ?
-                .call(/*return_error=*/ false)
-                ?
-                ;
-            assert_eq!(val, 57);
-        }
-    }
-    Ok(())
-}
-
-fn main() -> Result<(), ()> {
-    test1().expect_err("test1 should fail");
-    test2()
-    ?
-    ;
-    Ok(())
-}
diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs
deleted file mode 100644
index 6385bfa160d..00000000000
--- a/tests/run-coverage/unreachable.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![feature(core_intrinsics)]
-#![feature(coverage_attribute)]
-// compile-flags: --edition=2021
-
-// <https://github.com/rust-lang/rust/issues/116171>
-// If we instrument a function for coverage, but all of its counter-increment
-// statements are removed by MIR optimizations, LLVM will think it isn't
-// instrumented and it will disappear from coverage maps and coverage reports.
-// Most MIR opts won't cause this because they tend not to remove statements
-// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
-// with `TerminatorKind::Unreachable`.
-
-use std::hint::{black_box, unreachable_unchecked};
-
-static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
-
-fn unreachable_function() {
-    unsafe { unreachable_unchecked() }
-}
-
-// Use an intrinsic to more reliably trigger unreachable-propagation.
-fn unreachable_intrinsic() {
-    unsafe { std::intrinsics::unreachable() }
-}
-
-#[coverage(off)]
-fn main() {
-    if black_box(false) {
-        UNREACHABLE_CLOSURE();
-    }
-    if black_box(false) {
-        unreachable_function();
-    }
-    if black_box(false) {
-        unreachable_intrinsic();
-    }
-}
diff --git a/tests/run-coverage/unused.rs b/tests/run-coverage/unused.rs
deleted file mode 100644
index d985af13547..00000000000
--- a/tests/run-coverage/unused.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)]
-
-fn foo<T>(x: T) {
-    let mut i = 0;
-    while i < 10 {
-        i != 0 || i != 0;
-        i += 1;
-    }
-}
-
-fn unused_template_func<T>(x: T) {
-    let mut i = 0;
-    while i < 10 {
-        i != 0 || i != 0;
-        i += 1;
-    }
-}
-
-fn unused_func(mut a: u32) {
-    if a != 0 {
-        a += 1;
-    }
-}
-
-fn unused_func2(mut a: u32) {
-    if a != 0 {
-        a += 1;
-    }
-}
-
-fn unused_func3(mut a: u32) {
-    if a != 0 {
-        a += 1;
-    }
-}
-
-fn main() -> Result<(), u8> {
-    foo::<u32>(0);
-    foo::<f32>(0.0);
-    Ok(())
-}
diff --git a/tests/run-coverage/while.rs b/tests/run-coverage/while.rs
deleted file mode 100644
index 781b90b3566..00000000000
--- a/tests/run-coverage/while.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let num = 9;
-    while num >= 10 {
-    }
-}
diff --git a/tests/run-coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs
deleted file mode 100644
index b2f0eee2cc0..00000000000
--- a/tests/run-coverage/while_early_ret.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#![allow(unused_assignments)]
-// failure-status: 1
-
-fn main() -> Result<(), u8> {
-    let mut countdown = 10;
-    while
-        countdown
-            >
-        0
-    {
-        if
-            countdown
-                <
-            5
-        {
-            return
-                if
-                    countdown
-                        >
-                    8
-                {
-                    Ok(())
-                }
-                else
-                {
-                    Err(1)
-                }
-                ;
-        }
-        countdown
-            -=
-        1
-        ;
-    }
-    Ok(())
-}
-
-// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
-// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
-// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
-// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
-// to the coverage test for early returns, but this is a limitation that should be fixed.
diff --git a/tests/run-coverage/yield.rs b/tests/run-coverage/yield.rs
deleted file mode 100644
index b7e2ba31b59..00000000000
--- a/tests/run-coverage/yield.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![feature(coroutines, coroutine_trait)]
-#![allow(unused_assignments)]
-
-use std::ops::{Coroutine, CoroutineState};
-use std::pin::Pin;
-
-fn main() {
-    let mut coroutine = || {
-        yield 1;
-        return "foo";
-    };
-
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Yielded(1) => {}
-        _ => panic!("unexpected value from resume"),
-    }
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Complete("foo") => {}
-        _ => panic!("unexpected value from resume"),
-    }
-
-    let mut coroutine = || {
-        yield 1;
-        yield 2;
-        yield 3;
-        return "foo";
-    };
-
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Yielded(1) => {}
-        _ => panic!("unexpected value from resume"),
-    }
-    match Pin::new(&mut coroutine).resume(()) {
-        CoroutineState::Yielded(2) => {}
-        _ => panic!("unexpected value from resume"),
-    }
-}
diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs
index f50a9b96d81..b6379c05a85 100644
--- a/tests/rustdoc/const-effect-param.rs
+++ b/tests/rustdoc/const-effect-param.rs
@@ -1,3 +1,5 @@
+// Check that we don't render host effect parameters & arguments.
+
 #![crate_name = "foo"]
 #![feature(effects, const_trait_impl)]
 
diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs
new file mode 100644
index 00000000000..b0c21ffaeb9
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs
@@ -0,0 +1,16 @@
+#![feature(effects, const_trait_impl)]
+
+#[const_trait]
+pub trait Resource {}
+
+pub const fn load<R: ~const Resource>() -> i32 {
+    0
+}
+
+pub const fn lock<R: Resource>() {}
+
+#[allow(non_upper_case_globals)]
+pub trait Clash<const host: u64> {}
+
+#[allow(non_upper_case_globals)]
+pub const fn clash<T: Clash<host>, const host: u64>() {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs b/tests/rustdoc/inline_cross/auxiliary/const-fn.rs
deleted file mode 100644
index 26332b419b6..00000000000
--- a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![feature(effects)]
-
-pub const fn load() -> i32 {
-    0
-}
diff --git a/tests/rustdoc/inline_cross/const-effect-param.rs b/tests/rustdoc/inline_cross/const-effect-param.rs
new file mode 100644
index 00000000000..1d003e28f36
--- /dev/null
+++ b/tests/rustdoc/inline_cross/const-effect-param.rs
@@ -0,0 +1,29 @@
+// Regression test for issue #116629.
+// Check that we don't render host effect parameters & arguments.
+
+// aux-crate:const_effect_param=const-effect-param.rs
+// edition: 2021
+#![crate_name = "user"]
+
+// Don't render the host param on `load` and the host arg `host` passed to `Resource`.
+// @has user/fn.load.html
+// @has - '//pre[@class="rust item-decl"]' "pub const fn load<R>() -> i32\
+//     where \
+//         R: Resource"
+pub use const_effect_param::load;
+
+// Don't render the host arg `true` passed to `Resource`.
+// @has user/fn.lock.html
+// @has - '//pre[@class="rust item-decl"]' "pub const fn lock<R>()\
+//     where \
+//         R: Resource"
+pub use const_effect_param::lock;
+
+// Regression test for an issue introduced in PR #116670.
+// Don't hide the const param `host` since it actually isn't the host effect param.
+// @has user/fn.clash.html
+// @has - '//pre[@class="rust item-decl"]' \
+//    "pub const fn clash<T, const host: u64>()\
+//     where \
+//         T: Clash<host>"
+pub use const_effect_param::clash;
diff --git a/tests/rustdoc/inline_cross/const-fn.rs b/tests/rustdoc/inline_cross/const-fn.rs
deleted file mode 100644
index 24934b873c2..00000000000
--- a/tests/rustdoc/inline_cross/const-fn.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Regression test for issue #116629.
-// Check that we render the correct generic params of const fn
-
-// aux-crate:const_fn=const-fn.rs
-// edition: 2021
-#![crate_name = "user"]
-
-// @has user/fn.load.html
-// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32"
-pub use const_fn::load;
diff --git a/tests/rustdoc/issue-115295-macro-const-display.rs b/tests/rustdoc/issue-115295-macro-const-display.rs
new file mode 100644
index 00000000000..2916c7a84a1
--- /dev/null
+++ b/tests/rustdoc/issue-115295-macro-const-display.rs
@@ -0,0 +1,40 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+pub trait Trait<T> {}
+
+// @has foo/struct.WithConst.html
+pub struct WithConst<const N: usize>;
+
+macro_rules! spans_from_macro {
+    () => {
+        impl WithConst<42> {
+            pub fn new() -> Self {
+                Self
+            }
+        }
+        impl Trait<WithConst<42>> for WithConst<42> {}
+        impl Trait<WithConst<43>> for WithConst<{ 43 }> {}
+        impl Trait<WithConst<{ 44 }>> for WithConst<44> {}
+        pub struct Other {
+            pub field: WithConst<42>,
+        }
+    };
+}
+
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<41>> for WithConst<41>"
+impl Trait<WithConst<41>> for WithConst<41> {}
+
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl WithConst<42>"
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<42>> for WithConst<42>"
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<43>> for WithConst<{ 43 }>"
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<44>> for WithConst<44>"
+
+// @has foo/struct.Other.html
+// @has - //pre "pub field: WithConst<42>"
+spans_from_macro!();
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 3d6cff00a6d..685a029dcb2 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -130,7 +130,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| {
                     g(ExprKind::Closure(Box::new(Closure {
                         binder: ClosureBinder::NotPresent,
-                        capture_clause: CaptureBy::Value,
+                        capture_clause: CaptureBy::Value { move_kw: DUMMY_SP },
                         constness: Const::No,
                         asyncness: Async::No,
                         movability: Movability::Movable,
diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr
index d1ebca8a29e..c15d19b1594 100644
--- a/tests/ui/atomic-from-mut-not-available.stderr
+++ b/tests/ui/atomic-from-mut-not-available.stderr
@@ -3,6 +3,10 @@ error[E0599]: no function or associated item named `from_mut` found for struct `
    |
 LL |     core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
    |                                    ^^^^^^^^ function or associated item not found in `AtomicU64`
+   |
+note: if you're trying to build a new `AtomicU64`, consider using `AtomicU64::new` which returns `AtomicU64`
+  --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL
+   = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.fixed b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed
new file mode 100644
index 00000000000..b47372c9064
--- /dev/null
+++ b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+fn foo() {}
+fn main() {
+    let mut y = 42;
+    let x = &mut y;
+    foo();
+    *x = 0;  //~ ERROR invalid left-hand side of assignment
+    let _ = x;
+    println!("{y}");
+}
diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.rs b/tests/ui/binop/false-binop-caused-by-missing-semi.rs
new file mode 100644
index 00000000000..14671de7e51
--- /dev/null
+++ b/tests/ui/binop/false-binop-caused-by-missing-semi.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+fn foo() {}
+fn main() {
+    let mut y = 42;
+    let x = &mut y;
+    foo()
+    *x = 0;  //~ ERROR invalid left-hand side of assignment
+    let _ = x;
+    println!("{y}");
+}
diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.stderr b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr
new file mode 100644
index 00000000000..fca042b1c57
--- /dev/null
+++ b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr
@@ -0,0 +1,17 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/false-binop-caused-by-missing-semi.rs:7:8
+   |
+LL | /     foo()
+LL | |     *x = 0;
+   | |      - ^
+   | |______|
+   |        cannot assign to this expression
+   |
+help: you might have meant to write a semicolon here
+   |
+LL |     foo();
+   |          +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
index 0807f459029..85426dd9a5e 100644
--- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
@@ -5,10 +5,10 @@ LL |     let _b = || { match l1 { L1::A => () } };
    |                         ^^ pattern `L1::B` not covered
    |
 note: `L1` defined here
-  --> $DIR/non-exhaustive-match.rs:12:14
+  --> $DIR/non-exhaustive-match.rs:12:6
    |
 LL | enum L1 { A, B }
-   |      --      ^ not covered
+   |      ^^      - not covered
    = note: the matched value is of type `L1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/consts/assert-type-intrinsics.rs b/tests/ui/consts/assert-type-intrinsics.rs
index b4fd423becd..32b5f5c92c5 100644
--- a/tests/ui/consts/assert-type-intrinsics.rs
+++ b/tests/ui/consts/assert-type-intrinsics.rs
@@ -1,5 +1,4 @@
 #![feature(never_type)]
-#![feature(const_assert_type2)]
 #![feature(core_intrinsics)]
 
 use std::intrinsics;
diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr
index 3c03b03deee..66c4f0f9cd6 100644
--- a/tests/ui/consts/assert-type-intrinsics.stderr
+++ b/tests/ui/consts/assert-type-intrinsics.stderr
@@ -1,20 +1,20 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/assert-type-intrinsics.rs:12:9
+  --> $DIR/assert-type-intrinsics.rs:11:9
    |
 LL |         MaybeUninit::<!>::uninit().assume_init();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:11:36
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/assert-type-intrinsics.rs:16:9
+  --> $DIR/assert-type-intrinsics.rs:15:9
    |
 LL |         intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:15:9
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/assert-type-intrinsics.rs:20:9
+  --> $DIR/assert-type-intrinsics.rs:19:9
    |
 LL |         intrinsics::assert_zero_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:19:9
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
index 174103eeba4..eb8b8ac7534 100644
--- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
+++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -6,13 +6,17 @@ LL |     let _: [Option<Bar>; 2] = [no_copy(); 2];
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
 LL + #[derive(Copy)]
 LL | struct Bar;
    |
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Option<Bar> = no_copy();
+LL ~     let _: [Option<Bar>; 2] = [ARRAY_REPEAT_VALUE; 2];
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr
index 06fa4b0b1f3..858ffa820e2 100644
--- a/tests/ui/consts/const-blocks/trait-error.stderr
+++ b/tests/ui/consts/const-blocks/trait-error.stderr
@@ -10,9 +10,13 @@ note: required for `Foo<String>` to implement `Copy`
 LL | #[derive(Copy, Clone)]
    |          ^^^^ unsatisfied trait bound introduced in this `derive` macro
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Foo<String> = Foo(String::new());
+LL ~     [ARRAY_REPEAT_VALUE; 4];
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs
index a40290eca09..0483800efef 100644
--- a/tests/ui/consts/const-fn-in-vec.rs
+++ b/tests/ui/consts/const-fn-in-vec.rs
@@ -1,7 +1,11 @@
+static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
+//~^ ERROR the trait bound `String: Copy` is not satisfied
+
 fn main() {
     // should hint to create an inline `const` block
     // or to create a new `const` item
-    let strings: [String; 5] = [String::new(); 5];
+    let _strings: [String; 5] = [String::new(); 5];
+    //~^ ERROR the trait bound `String: Copy` is not satisfied
+    let _maybe_strings: [Option<String>; 5] = [None; 5];
     //~^ ERROR the trait bound `String: Copy` is not satisfied
-    println!("{:?}", strings);
 }
diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr
index 9eb7524b504..4593034bfae 100644
--- a/tests/ui/consts/const-fn-in-vec.stderr
+++ b/tests/ui/consts/const-fn-in-vec.stderr
@@ -1,13 +1,47 @@
 error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/const-fn-in-vec.rs:4:33
+  --> $DIR/const-fn-in-vec.rs:1:47
    |
-LL |     let strings: [String; 5] = [String::new(); 5];
-   |                                 ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
+   |                                               ^^^^ the trait `Copy` is not implemented for `String`
    |
+   = note: required for `Option<String>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
+   |
+LL + const ARRAY_REPEAT_VALUE: Option<String> = None;
+LL ~ static _MAYBE_STRINGS: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/const-fn-in-vec.rs:7:34
+   |
+LL |     let _strings: [String; 5] = [String::new(); 5];
+   |                                  ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: the `Copy` trait is required because this value will be copied for each element of the array
+   = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: String = String::new();
+LL ~     let _strings: [String; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/const-fn-in-vec.rs:9:48
+   |
+LL |     let _maybe_strings: [Option<String>; 5] = [None; 5];
+   |                                                ^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: required for `Option<String>` to implement `Copy`
+   = note: the `Copy` trait is required because this value will be copied for each element of the array
+   = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Option<String> = None;
+LL ~     let _maybe_strings: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs
new file mode 100644
index 00000000000..ffeb02d78b8
--- /dev/null
+++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs
@@ -0,0 +1,96 @@
+// Check that deriving builtin traits for a packed struct with
+// non-Copy fields emits move errors along with an additional
+// diagnostic note explaining the reason
+// See issue #117406
+
+use std::fmt::{Debug, Formatter, Result};
+use std::cmp::Ordering;
+
+// Packed + derives: additional diagnostic should be emitted
+// for each of Debug, PartialEq and PartialOrd
+#[repr(packed)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+struct StructA(String);
+//~^ ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+
+
+// Unrelated impl: additinal diagnostic should NOT be emitted
+impl StructA {
+    fn fmt(&self) -> String {
+        self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference
+    }
+}
+
+// Packed + manual impls: additional diagnostic should NOT be emitted
+#[repr(packed)]
+struct StructB(String);
+
+impl Debug for StructB {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference
+        write!(f, "{}", x)
+    }
+}
+
+impl PartialEq for StructB {
+    fn eq(&self, other: &StructB) -> bool {
+        ({ self.0 }) == ({ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+impl PartialOrd for StructB {
+    fn partial_cmp(&self, other: &StructB) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+// NOT packed + derives: additinal diagnostic should NOT be emitted
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+struct StructC(String);
+
+// NOT packed + manual impls: additinal dignostic should NOT be emitted
+struct StructD(String);
+
+impl Debug for StructD {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference
+        write!(f, "{}", x)
+    }
+}
+
+impl PartialEq for StructD {
+    fn eq(&self, other: &StructD) -> bool {
+        ({ self.0 }) == ({ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+impl PartialOrd for StructD {
+    fn partial_cmp(&self, other: &StructD) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+// Packed + derives but the move is outside of a derive
+// expansion: additinal diagnostic should NOT be emitted
+fn func(arg: &StructA) -> String {
+    arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference
+}
+
+fn main(){
+}
diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
new file mode 100644
index 00000000000..c538061b365
--- /dev/null
+++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
@@ -0,0 +1,174 @@
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |          ----- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                 --------- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                 --------- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                ---------- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                ---------- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                            --- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                            --- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                                 ---- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
+   |
+LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+   |                                                       ----- in this derive macro expansion
+LL | struct StructA(String);
+   |                ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:28:9
+   |
+LL |         self.0
+   |         ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:38:20
+   |
+LL |         let x = &{ self.0 };
+   |                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:45:12
+   |
+LL |         ({ self.0 }) == ({ other.0 })
+   |            ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:45:28
+   |
+LL |         ({ self.0 }) == ({ other.0 })
+   |                            ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:53:36
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+   |                                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:53:49
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+   |                                                 ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:68:20
+   |
+LL |         let x = &{ self.0 };
+   |                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:75:12
+   |
+LL |         ({ self.0 }) == ({ other.0 })
+   |            ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:75:28
+   |
+LL |         ({ self.0 }) == ({ other.0 })
+   |                            ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `self` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:83:36
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+   |                                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `other` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:83:49
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+   |                                                 ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `arg` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed-move-errors.rs:92:5
+   |
+LL |     arg.0
+   |     ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index 0cfe03869af..bb1fab343a3 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -36,6 +36,7 @@ LL | #[repr(packed)]
 LL | struct X(Y);
    |          ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait
    |
+   = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error; 2 warnings emitted
diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr
index 603bc5237ea..ced478d65ea 100644
--- a/tests/ui/error-codes/E0004.stderr
+++ b/tests/ui/error-codes/E0004.stderr
@@ -5,12 +5,12 @@ LL |     match x {
    |           ^ pattern `Terminator::HastaLaVistaBaby` not covered
    |
 note: `Terminator` defined here
-  --> $DIR/E0004.rs:2:5
+  --> $DIR/E0004.rs:1:6
    |
 LL | enum Terminator {
-   |      ----------
+   |      ^^^^^^^^^^
 LL |     HastaLaVistaBaby,
-   |     ^^^^^^^^^^^^^^^^ not covered
+   |     ---------------- not covered
    = note: the matched value is of type `Terminator`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
index eb61c4cf159..8af0eedc82b 100644
--- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
+++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
@@ -134,13 +134,13 @@ LL |     match Foo::A {
    |           ^^^^^^ pattern `Foo::C` not covered
    |
 note: `Foo` defined here
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:16:9
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:10
    |
 LL |     enum Foo {
-   |          ---
+   |          ^^^
 ...
 LL |         C,
-   |         ^ not covered
+   |         - not covered
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
new file mode 100644
index 00000000000..e19dcf9f6a5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
@@ -0,0 +1,15 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+enum Alpha {
+    One(u8),
+    Two(u8),
+}
+
+fn main() {
+    offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One`
+    offset_of!(Alpha, One); //~ ERROR `One` is an enum variant; expected field at end of `offset_of`
+                            //~| ERROR using enums in offset_of is experimental
+    offset_of!(Alpha, Two.0); //~ ERROR using enums in offset_of is experimental
+}
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
new file mode 100644
index 00000000000..893f7870237
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
@@ -0,0 +1,37 @@
+error[E0573]: expected type, found variant `Alpha::One`
+  --> $DIR/feature-gate-offset-of-enum.rs:11:16
+   |
+LL |     offset_of!(Alpha::One, 0);
+   |                ^^^^^^^^^^
+   |                |
+   |                not a type
+   |                help: try using the variant's enum: `Alpha`
+
+error[E0658]: using enums in offset_of is experimental
+  --> $DIR/feature-gate-offset-of-enum.rs:12:23
+   |
+LL |     offset_of!(Alpha, One);
+   |                       ^^^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable
+
+error[E0795]: `One` is an enum variant; expected field at end of `offset_of`
+  --> $DIR/feature-gate-offset-of-enum.rs:12:23
+   |
+LL |     offset_of!(Alpha, One);
+   |                       ^^^ enum variant
+
+error[E0658]: using enums in offset_of is experimental
+  --> $DIR/feature-gate-offset-of-enum.rs:14:23
+   |
+LL |     offset_of!(Alpha, Two.0);
+   |                       ^^^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0573, E0658, E0795.
+For more information about an error, try `rustc --explain E0573`.
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
index 7b168707239..e2d51c6649a 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
@@ -1,4 +1,4 @@
-// check-pass
+// known-bug: #117606
 
 #![feature(associated_type_defaults)]
 
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr
new file mode 100644
index 00000000000..abad0f25c0f
--- /dev/null
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30
+   |
+LL |     type Bar<T>: Baz<Self> = i32;
+   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`
+   |
+note: required for `i32` to implement `Baz<Self>`
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23
+   |
+LL | impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {}
+   |                       ^^^^^^     ^^^                   ------- unsatisfied trait bound introduced here
+note: required by a bound in `Foo::Bar`
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18
+   |
+LL |     type Bar<T>: Baz<Self> = i32;
+   |                  ^^^^^^^^^ required by this bound in `Foo::Bar`
+help: consider further restricting the associated type
+   |
+LL | trait Foo where <Self as Foo>::Bar<()>: Eq<i32> {
+   |           +++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs
new file mode 100644
index 00000000000..5ef9437c968
--- /dev/null
+++ b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+trait Database: for<'r> HasValueRef<'r, Database = Self> {}
+
+trait HasValueRef<'r> {
+    type Database: Database;
+}
+
+struct Any;
+
+impl Database for Any {}
+
+impl<'r> HasValueRef<'r> for Any {
+    // Make sure we don't have issues when the GAT assumption
+    // `<Any as HasValue<'r>>::Database = Any` isn't universally
+    // parameterized over `'r`.
+    type Database = Any;
+}
+
+fn main() {}
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index 1fd61084130..e0dc13c0c95 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5:
+thread 'main' panicked at library/alloc/src/raw_vec.rs:545:5:
 capacity overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs
new file mode 100644
index 00000000000..af6ffe83394
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs
@@ -0,0 +1,11 @@
+// edition:2021
+// https://github.com/rust-lang/rust/issues/117547
+
+trait T {}
+
+trait MyTrait {
+    async fn foo() -> &'static impl T;
+    //~^ ERROR the associated type `<Self as MyTrait>::{opaque#0}` may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr
new file mode 100644
index 00000000000..7c9028a8cd5
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr
@@ -0,0 +1,14 @@
+error[E0310]: the associated type `<Self as MyTrait>::{opaque#0}` may not live long enough
+  --> $DIR/async-and-ret-ref.rs:7:5
+   |
+LL |     async fn foo() -> &'static impl T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     the associated type `<Self as MyTrait>::{opaque#0}` must be valid for the static lifetime...
+   |     ...so that the reference type `&'static impl T` does not outlive the data it points at
+   |
+   = help: consider adding an explicit lifetime bound `<Self as MyTrait>::{opaque#0}: 'static`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/late-bound-lifetimes/predicate-is-global.rs b/tests/ui/late-bound-lifetimes/predicate-is-global.rs
new file mode 100644
index 00000000000..be017a3f94f
--- /dev/null
+++ b/tests/ui/late-bound-lifetimes/predicate-is-global.rs
@@ -0,0 +1,40 @@
+// check-pass
+
+trait Foo {
+    type Assoc;
+
+    fn do_it(_: &Self::Assoc)
+    where
+        for<'a> Self: Baz<'a>;
+}
+
+trait Baz<'a>: Foo {}
+
+impl Foo for () {
+    type Assoc = Inherent;
+
+    // Ensure that the `for<'a> Self: Baz<'a>` predicate, which has
+    // a supertrait `for<'a> Self: Foo`, does not cause us to fail
+    // to normalize `Self::Assoc`.
+    fn do_it(x: &Self::Assoc)
+    where
+        for<'a> Self: Baz<'a>,
+    {
+        x.inherent();
+    }
+}
+
+struct Inherent;
+impl Inherent {
+    fn inherent(&self) {}
+}
+
+// This trivial bound doesn't hold, but the unused lifetime tripped up that check after #117589, and
+// showed up in its crater results (in `soa-derive 0.13.0`).
+fn do_it()
+where
+    for<'a> Inherent: Clone,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index f1bbd4a6210..70ca00285c4 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -115,6 +115,7 @@ fn test_expr() {
         "a + b * c - d + -1 * -2 - -3",
         "a + b * c - d + - 1 * - 2 - - 3"
     );
+    c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME
 
     // ExprKind::Unary
     c2!(expr, [ *expr ], "*expr", "* expr");
@@ -137,6 +138,7 @@ fn test_expr() {
 
     // ExprKind::If
     c1!(expr, [ if true {} ], "if true {}");
+    c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME
     c2!(expr,
         [ if ::std::blah() { } else { } ],
         "if ::std::blah() {} else {}",
@@ -799,3 +801,32 @@ fn test_vis() {
     assert_eq!(inherited_vis!(struct), "");
     assert_eq!(stringify!(), "");
 }
+
+macro_rules! p {
+    ([$($tt:tt)*], $s:literal) => {
+        assert_eq!(stringify!($($tt)*), $s);
+    };
+}
+
+#[test]
+fn test_punct() {
+    // For all these cases, we must preserve spaces between the tokens.
+    // Otherwise, any old proc macro that parses pretty-printed code might glue
+    // together tokens that shouldn't be glued.
+    p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >");
+    p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME
+    p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #");
+    p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME
+    p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME
+    p!([ -> -> <- <- => =>], "-> -> <- <- => =>");
+    p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME
+    p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /=");
+    p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ],
+        "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>=");
+
+    // For these one we must insert spaces between adjacent tokens, again due
+    // to proc macros.
+    p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME
+    p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME
+    p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME
+}
diff --git a/tests/ui/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr
index 7b8bdfe0053..40be39ec077 100644
--- a/tests/ui/match/match_non_exhaustive.stderr
+++ b/tests/ui/match/match_non_exhaustive.stderr
@@ -5,10 +5,10 @@ LL |     match l { L::A => () };
    |           ^ pattern `L::B` not covered
    |
 note: `L` defined here
-  --> $DIR/match_non_exhaustive.rs:10:13
+  --> $DIR/match_non_exhaustive.rs:10:6
    |
 LL | enum L { A, B }
-   |      -      ^ not covered
+   |      ^      - not covered
    = note: the matched value is of type `L`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
index a9e9c679fdb..ccdd9a95451 100644
--- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::CONST;
+LL |     <S as A>::CONST;
    |     ~~~~~~~~~~
-LL |     <T as B>::CONST;
+LL |     <S as B>::CONST;
    |     ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr
index 901bfc30a3f..4172120770c 100644
--- a/tests/ui/methods/disambiguate-multiple-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <S as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <S as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-impl.rs:34:16
diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
index 0f9c60ce243..2778f254a56 100644
--- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
@@ -37,12 +37,12 @@ LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:20:16
@@ -62,10 +62,10 @@ LL |     const CONST: usize;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = A::CONST;
-   |             ~~~
-LL |     let _ = B::CONST;
-   |             ~~~
+LL |     let _ = <T as A>::CONST;
+   |             ~~~~~~~~~~
+LL |     let _ = <T as B>::CONST;
+   |             ~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/disambiguate-multiple-trait-2.rs:52:12
@@ -98,10 +98,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:49:16
@@ -121,9 +121,9 @@ LL |     const CONST: usize = 1;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr
index 9a50d51245b..e00498ca62b 100644
--- a/tests/ui/methods/disambiguate-multiple-trait.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait.rs:27:16
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
index 601e6bbb006..9a84768a9f4 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -16,12 +16,12 @@ LL | trait B { fn foo(&self); }
    |           ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 4e83e4b77f1..755179650bb 100644
--- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -54,8 +54,8 @@ LL |     let z = NuisanceFoo::foo(x);
    |             ~~~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #3
    |
-LL |     let z = FinalFoo::foo(x);
-   |             ~~~~~~~~~~~~~~~~
+LL |     let z = FinalFoo::foo(&x);
+   |             ~~~~~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
diff --git a/tests/ui/mir/addrof_alignment.rs b/tests/ui/mir/alignment/addrof_alignment.rs
index 892638bfb92..f3423e97a8a 100644
--- a/tests/ui/mir/addrof_alignment.rs
+++ b/tests/ui/mir/alignment/addrof_alignment.rs
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-wasm32-bare: No panic messages
 // compile-flags: -C debug-assertions
 
 struct Misalignment {
@@ -9,7 +8,7 @@ struct Misalignment {
 fn main() {
     let items: [Misalignment; 2] = [Misalignment { a: 0 }, Misalignment { a: 1 }];
     unsafe {
-        let ptr: *const Misalignment = items.as_ptr().cast::<u8>().add(1).cast::<Misalignment>();
+        let ptr: *const Misalignment = items.as_ptr().byte_add(1);
         let _ptr = core::ptr::addr_of!((*ptr).a);
     }
 }
diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs
index 56388c1047e..74ba1fde649 100644
--- a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs
+++ b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs
@@ -11,9 +11,9 @@
 
 fn main() {
     let mut x = [0u64; 2];
-    let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
+    let ptr = x.as_mut_ptr();
     unsafe {
-        let misaligned = ptr.add(4).cast::<u64>();
+        let misaligned = ptr.byte_add(4);
         assert!(misaligned.addr() % 8 != 0);
         assert!(misaligned.addr() % 4 == 0);
         *misaligned = 42;
diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/alignment/misaligned_lhs.rs
index d1bf3d46a7c..97644ba8e09 100644
--- a/tests/ui/mir/mir_alignment_check.rs
+++ b/tests/ui/mir/alignment/misaligned_lhs.rs
@@ -6,8 +6,8 @@
 
 fn main() {
     let mut x = [0u32; 2];
-    let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
+    let ptr = x.as_mut_ptr();
     unsafe {
-        *(ptr.add(1).cast::<u32>()) = 42;
+        *(ptr.byte_add(1)) = 42;
     }
 }
diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs
new file mode 100644
index 00000000000..8534bc71a3a
--- /dev/null
+++ b/tests/ui/mir/alignment/misaligned_rhs.rs
@@ -0,0 +1,13 @@
+// run-fail
+// ignore-wasm32-bare: No panic messages
+// ignore-i686-pc-windows-msvc: #112480
+// compile-flags: -C debug-assertions
+// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
+
+fn main() {
+    let mut x = [0u32; 2];
+    let ptr = x.as_mut_ptr();
+    unsafe {
+        let _v = *(ptr.byte_add(1));
+    }
+}
diff --git a/tests/ui/mir/alignment/packed.rs b/tests/ui/mir/alignment/packed.rs
new file mode 100644
index 00000000000..754698591e3
--- /dev/null
+++ b/tests/ui/mir/alignment/packed.rs
@@ -0,0 +1,29 @@
+// run-pass
+// compile-flags: -C debug-assertions
+
+#![feature(strict_provenance, pointer_is_aligned)]
+
+#[repr(packed)]
+struct Misaligner {
+    _head: u8,
+    tail: u64,
+}
+
+fn main() {
+    let memory = [Misaligner { _head: 0, tail: 0}, Misaligner { _head: 0, tail: 0}];
+    // Test that we can use addr_of! to get the address of a packed member which according to its
+    // type is not aligned, but because it is a projection from a packed type is a valid place.
+    let ptr0 = std::ptr::addr_of!(memory[0].tail);
+    let ptr1 = std::ptr::addr_of!(memory[0].tail);
+    // Even if ptr0 happens to be aligned by chance, ptr1 is not.
+    assert!(!ptr0.is_aligned() || !ptr1.is_aligned());
+
+    // And also test that we can get the addr of a packed struct then do a member read from it.
+    unsafe {
+        let ptr = std::ptr::addr_of!(memory[0]);
+        let _tail = (*ptr).tail;
+
+        let ptr = std::ptr::addr_of!(memory[1]);
+        let _tail = (*ptr).tail;
+    }
+}
diff --git a/tests/ui/mir/alignment/place_computation.rs b/tests/ui/mir/alignment/place_computation.rs
new file mode 100644
index 00000000000..fdd4864250a
--- /dev/null
+++ b/tests/ui/mir/alignment/place_computation.rs
@@ -0,0 +1,16 @@
+// run-pass
+// compile-flags: -C debug-assertions
+
+#[repr(align(8))]
+struct Misalignment {
+    a: u8,
+}
+
+fn main() {
+    let mem = 0u64;
+    let ptr = &mem as *const u64 as *const Misalignment;
+    unsafe {
+        let ptr = ptr.byte_add(1);
+        let _ref: &u8 = &(*ptr).a;
+    }
+}
diff --git a/tests/ui/mir/alignment/place_without_read.rs b/tests/ui/mir/alignment/place_without_read.rs
new file mode 100644
index 00000000000..b4be7a50f61
--- /dev/null
+++ b/tests/ui/mir/alignment/place_without_read.rs
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags: -C debug-assertions
+
+fn main() {
+    let ptr = 1 as *const u16;
+    unsafe {
+        let _ = *ptr;
+    }
+}
diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs
new file mode 100644
index 00000000000..29af21dffc1
--- /dev/null
+++ b/tests/ui/mir/alignment/two_pointers.rs
@@ -0,0 +1,15 @@
+// run-fail
+// ignore-wasm32-bare: No panic messages
+// ignore-i686-pc-windows-msvc: #112480
+// compile-flags: -C debug-assertions
+// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
+
+fn main() {
+    let x = [0u32; 2];
+    let ptr = x.as_ptr();
+    let mut dest = 0u32;
+    let dest_ptr = &mut dest as *mut u32;
+    unsafe {
+        *dest_ptr = *(ptr.byte_add(1));
+    }
+}
diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr
new file mode 100644
index 00000000000..475b41388d3
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr
@@ -0,0 +1,6 @@
+warning: unstable feature specified for `-Ctarget-feature`: `nontrapping-fptoint`
+   |
+   = note: this feature is not stably supported; its behavior can change in the future
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs
index e8b5a08377b..a2d6aace47d 100644
--- a/tests/ui/offset-of/offset-of-enum.rs
+++ b/tests/ui/offset-of/offset-of-enum.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of, offset_of_enum)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 6fa30d63fb8..b7affdb7943 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of, offset_of_enum)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/parser/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr
index e645b68ba87..8250dd1ea2e 100644
--- a/tests/ui/parser/emoji-identifiers.stderr
+++ b/tests/ui/parser/emoji-identifiers.stderr
@@ -75,6 +75,12 @@ LL |     👀::full_of✨()
    |         |
    |         function or associated item not found in `👀`
    |         help: there is an associated function with a similar name: `full_of_✨`
+   |
+note: if you're trying to build a new `👀`, consider using `👀::full_of_✨` which returns `👀`
+  --> $DIR/emoji-identifiers.rs:4:5
+   |
+LL |     fn full_of_✨() -> 👀 {
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope
   --> $DIR/emoji-identifiers.rs:13:13
diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed
new file mode 100644
index 00000000000..eaae288864a
--- /dev/null
+++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub fn func<F>() where F: FnOnce() -> () {}
+//~^ ERROR expected one of
+//~| NOTE expected one of
+//~| NOTE `Fn` bounds require arguments in parentheses
+
+fn main() {}
diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs
new file mode 100644
index 00000000000..ea5c71150e8
--- /dev/null
+++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub fn func<F>() where F: FnOnce -> () {}
+//~^ ERROR expected one of
+//~| NOTE expected one of
+//~| NOTE `Fn` bounds require arguments in parentheses
+
+fn main() {}
diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr
new file mode 100644
index 00000000000..7cda667570d
--- /dev/null
+++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr
@@ -0,0 +1,11 @@
+error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
+  --> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34
+   |
+LL | pub fn func<F>() where F: FnOnce -> () {}
+   |                           -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
+   |                           |     |
+   |                           |     help: try adding parentheses
+   |                           `Fn` bounds require arguments in parentheses
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/issue-94866.stderr b/tests/ui/pattern/issue-94866.stderr
index b3c17ce8974..dee4b3f557c 100644
--- a/tests/ui/pattern/issue-94866.stderr
+++ b/tests/ui/pattern/issue-94866.stderr
@@ -5,10 +5,10 @@ LL |     match Enum::A {
    |           ^^^^^^^ pattern `Enum::B` not covered
    |
 note: `Enum` defined here
-  --> $DIR/issue-94866.rs:7:16
+  --> $DIR/issue-94866.rs:7:6
    |
 LL | enum Enum { A, B }
-   |      ----      ^ not covered
+   |      ^^^^      - not covered
    = note: the matched value is of type `Enum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs
new file mode 100644
index 00000000000..0b3e7ce9e9a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs
@@ -0,0 +1,24 @@
+#![feature(if_let_guard, let_chains)]
+
+fn main() {
+    let mut x = Some(String::new());
+    let ref mut y @ ref mut z = x;
+    //~^ ERROR: mutable more than once
+    let Some(ref mut y @ ref mut z) = x else { return };
+    //~^ ERROR: mutable more than once
+    if let Some(ref mut y @ ref mut z) = x {}
+    //~^ ERROR: mutable more than once
+    if let Some(ref mut y @ ref mut z) = x && true {}
+    //~^ ERROR: mutable more than once
+    while let Some(ref mut y @ ref mut z) = x {}
+    //~^ ERROR: mutable more than once
+    while let Some(ref mut y @ ref mut z) = x && true {}
+    //~^ ERROR: mutable more than once
+    match x {
+        ref mut y @ ref mut z => {} //~ ERROR: mutable more than once
+    }
+    match () {
+        () if let Some(ref mut y @ ref mut z) = x => {} //~ ERROR: mutable more than once
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr
new file mode 100644
index 00000000000..679fc83e7f5
--- /dev/null
+++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr
@@ -0,0 +1,66 @@
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:5:9
+   |
+LL |     let ref mut y @ ref mut z = x;
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |         |
+   |         value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:7:14
+   |
+LL |     let Some(ref mut y @ ref mut z) = x else { return };
+   |              ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |              |
+   |              value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:9:17
+   |
+LL |     if let Some(ref mut y @ ref mut z) = x {}
+   |                 ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |                 |
+   |                 value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:11:17
+   |
+LL |     if let Some(ref mut y @ ref mut z) = x && true {}
+   |                 ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |                 |
+   |                 value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:13:20
+   |
+LL |     while let Some(ref mut y @ ref mut z) = x {}
+   |                    ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |                    |
+   |                    value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:15:20
+   |
+LL |     while let Some(ref mut y @ ref mut z) = x && true {}
+   |                    ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |                    |
+   |                    value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:18:9
+   |
+LL |         ref mut y @ ref mut z => {}
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |         |
+   |         value is mutably borrowed by `y` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/conflicting_bindings.rs:21:24
+   |
+LL |         () if let Some(ref mut y @ ref mut z) = x => {}
+   |                        ^^^^^^^^^   --------- value is mutably borrowed by `z` here
+   |                        |
+   |                        value is mutably borrowed by `y` here
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
index ff29de03d6b..24f3eaa5230 100644
--- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
+++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
@@ -23,13 +23,13 @@ LL |     match HiddenEnum::A {
    |           ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered
    |
 note: `HiddenEnum` defined here
-  --> $DIR/auxiliary/hidden.rs:3:5
+  --> $DIR/auxiliary/hidden.rs:1:1
    |
 LL | pub enum HiddenEnum {
-   | -------------------
+   | ^^^^^^^^^^^^^^^^^^^
 LL |     A,
 LL |     B,
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `HiddenEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -44,13 +44,13 @@ LL |     match HiddenEnum::A {
    |           ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered
    |
 note: `HiddenEnum` defined here
-  --> $DIR/auxiliary/hidden.rs:3:5
+  --> $DIR/auxiliary/hidden.rs:1:1
    |
 LL | pub enum HiddenEnum {
-   | -------------------
+   | ^^^^^^^^^^^^^^^^^^^
 LL |     A,
 LL |     B,
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `HiddenEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -83,13 +83,13 @@ LL |     match InCrate::A {
    |           ^^^^^^^^^^ pattern `InCrate::C` not covered
    |
 note: `InCrate` defined here
-  --> $DIR/doc-hidden-non-exhaustive.rs:11:5
+  --> $DIR/doc-hidden-non-exhaustive.rs:7:6
    |
 LL | enum InCrate {
-   |      -------
+   |      ^^^^^^^
 ...
 LL |     C,
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `InCrate`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5b81a8c3d3c..8f9bd5bde89 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:58:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
@@ -11,25 +11,25 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:61:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:68:9
+  --> $DIR/empty-match.rs:78:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:71:9
+  --> $DIR/empty-match.rs:81:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match.rs:76:9
+  --> $DIR/empty-match.rs:86:9
    |
 LL |     let None = x;
    |         ^^^^ pattern `Some(_)` not covered
@@ -44,19 +44,19 @@ LL |     if let None = x { todo!() };
    |     ++              +++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:88:9
+  --> $DIR/empty-match.rs:98:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:91:9
+  --> $DIR/empty-match.rs:101:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:109:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -65,7 +65,7 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:111:20
+  --> $DIR/empty-match.rs:121:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL | struct NonEmptyStruct1;
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:113:20
+  --> $DIR/empty-match.rs:123:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
@@ -93,7 +93,7 @@ LL | struct NonEmptyStruct2(bool);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:115:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -107,7 +107,7 @@ LL | union NonEmptyUnion1 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:117:20
+  --> $DIR/empty-match.rs:127:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -121,42 +121,44 @@ LL | union NonEmptyUnion2 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:119:20
+  --> $DIR/empty-match.rs:129:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:33:5
+  --> $DIR/empty-match.rs:32:6
    |
 LL | enum NonEmptyEnum1 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:122:20
+  --> $DIR/empty-match.rs:132:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:40:5
+  --> $DIR/empty-match.rs:39:6
    |
 LL | enum NonEmptyEnum2 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
 ...
 LL |     Bar,
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:125:20
+  --> $DIR/empty-match.rs:135:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -166,11 +168,19 @@ note: `NonEmptyEnum5` defined here
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
+...
+LL |     V1, V2, V3, V4, V5,
+   |     --  --  --  --  -- not covered
+   |     |   |   |   |
+   |     |   |   |   not covered
+   |     |   |   not covered
+   |     |   not covered
+   |     not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:129:24
+  --> $DIR/empty-match.rs:139:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -184,7 +194,7 @@ LL +             _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:134:24
+  --> $DIR/empty-match.rs:144:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
@@ -203,7 +213,7 @@ LL +             NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:139:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
@@ -222,7 +232,7 @@ LL +             NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:144:24
+  --> $DIR/empty-match.rs:154:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
@@ -241,7 +251,7 @@ LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:149:24
+  --> $DIR/empty-match.rs:159:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
@@ -260,18 +270,19 @@ LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:154:24
+  --> $DIR/empty-match.rs:164:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:33:5
+  --> $DIR/empty-match.rs:32:6
    |
 LL | enum NonEmptyEnum1 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -281,21 +292,22 @@ LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:159:24
+  --> $DIR/empty-match.rs:169:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:40:5
+  --> $DIR/empty-match.rs:39:6
    |
 LL | enum NonEmptyEnum2 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
 ...
 LL |     Bar,
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
@@ -305,7 +317,7 @@ LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:164:24
+  --> $DIR/empty-match.rs:174:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -315,6 +327,14 @@ note: `NonEmptyEnum5` defined here
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
+...
+LL |     V1, V2, V3, V4, V5,
+   |     --  --  --  --  -- not covered
+   |     |   |   |   |
+   |     |   |   |   not covered
+   |     |   |   not covered
+   |     |   not covered
+   |     not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 6d17455086b..7f0389f40e2 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:58:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
@@ -11,25 +11,25 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:61:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:68:9
+  --> $DIR/empty-match.rs:78:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:71:9
+  --> $DIR/empty-match.rs:81:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match.rs:76:9
+  --> $DIR/empty-match.rs:86:9
    |
 LL |     let None = x;
    |         ^^^^ pattern `Some(_)` not covered
@@ -43,19 +43,19 @@ LL |     if let None = x { todo!() };
    |     ++              +++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:88:9
+  --> $DIR/empty-match.rs:98:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:91:9
+  --> $DIR/empty-match.rs:101:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:109:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -64,7 +64,7 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:111:20
+  --> $DIR/empty-match.rs:121:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
@@ -78,7 +78,7 @@ LL | struct NonEmptyStruct1;
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:113:20
+  --> $DIR/empty-match.rs:123:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
@@ -92,7 +92,7 @@ LL | struct NonEmptyStruct2(bool);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:115:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL | union NonEmptyUnion1 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:117:20
+  --> $DIR/empty-match.rs:127:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,42 +120,44 @@ LL | union NonEmptyUnion2 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:119:20
+  --> $DIR/empty-match.rs:129:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:33:5
+  --> $DIR/empty-match.rs:32:6
    |
 LL | enum NonEmptyEnum1 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:122:20
+  --> $DIR/empty-match.rs:132:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:40:5
+  --> $DIR/empty-match.rs:39:6
    |
 LL | enum NonEmptyEnum2 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
 ...
 LL |     Bar,
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:125:20
+  --> $DIR/empty-match.rs:135:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -165,11 +167,19 @@ note: `NonEmptyEnum5` defined here
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
+...
+LL |     V1, V2, V3, V4, V5,
+   |     --  --  --  --  -- not covered
+   |     |   |   |   |
+   |     |   |   |   not covered
+   |     |   |   not covered
+   |     |   not covered
+   |     not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:129:24
+  --> $DIR/empty-match.rs:139:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -183,7 +193,7 @@ LL +             _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:134:24
+  --> $DIR/empty-match.rs:144:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
@@ -202,7 +212,7 @@ LL +             NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:139:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
@@ -221,7 +231,7 @@ LL +             NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:144:24
+  --> $DIR/empty-match.rs:154:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
@@ -240,7 +250,7 @@ LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:149:24
+  --> $DIR/empty-match.rs:159:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
@@ -259,18 +269,19 @@ LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:154:24
+  --> $DIR/empty-match.rs:164:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:33:5
+  --> $DIR/empty-match.rs:32:6
    |
 LL | enum NonEmptyEnum1 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -280,21 +291,22 @@ LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:159:24
+  --> $DIR/empty-match.rs:169:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:40:5
+  --> $DIR/empty-match.rs:39:6
    |
 LL | enum NonEmptyEnum2 {
-   |      -------------
+   |      ^^^^^^^^^^^^^
+...
 LL |     Foo(bool),
-   |     ^^^ not covered
+   |     --- not covered
 ...
 LL |     Bar,
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
@@ -304,7 +316,7 @@ LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:164:24
+  --> $DIR/empty-match.rs:174:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -314,6 +326,14 @@ note: `NonEmptyEnum5` defined here
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
+...
+LL |     V1, V2, V3, V4, V5,
+   |     --  --  --  --  -- not covered
+   |     |   |   |   |
+   |     |   |   |   not covered
+   |     |   |   not covered
+   |     |   not covered
+   |     not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index d56d2e3c817..fe5d0bce14f 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -30,17 +30,17 @@ union NonEmptyUnion2 {
     bar: (),
 }
 enum NonEmptyEnum1 {
-    Foo(bool),
     //~^ NOTE `NonEmptyEnum1` defined here
     //~| NOTE `NonEmptyEnum1` defined here
-    //~| NOTE not covered
+    Foo(bool),
+    //~^ NOTE not covered
     //~| NOTE not covered
 }
 enum NonEmptyEnum2 {
-    Foo(bool),
     //~^ NOTE `NonEmptyEnum2` defined here
     //~| NOTE `NonEmptyEnum2` defined here
-    //~| NOTE not covered
+    Foo(bool),
+    //~^ NOTE not covered
     //~| NOTE not covered
     Bar,
     //~^ NOTE not covered
@@ -50,6 +50,16 @@ enum NonEmptyEnum5 {
     //~^ NOTE `NonEmptyEnum5` defined here
     //~| NOTE `NonEmptyEnum5` defined here
     V1, V2, V3, V4, V5,
+    //~^ NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
+    //~| NOTE not covered
 }
 
 fn empty_enum(x: EmptyEnum) {
diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr
index 6d5e2f410bc..9feedfde469 100644
--- a/tests/ui/pattern/usefulness/issue-35609.stderr
+++ b/tests/ui/pattern/usefulness/issue-35609.stderr
@@ -107,6 +107,9 @@ LL |     match Some(A) {
    |
 note: `Option<Enum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
    = note: the matched value is of type `Option<Enum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr
index b8b17918aef..8dc53491606 100644
--- a/tests/ui/pattern/usefulness/issue-39362.stderr
+++ b/tests/ui/pattern/usefulness/issue-39362.stderr
@@ -5,12 +5,12 @@ LL |     match f {
    |           ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered
    |
 note: `Foo` defined here
-  --> $DIR/issue-39362.rs:2:5
+  --> $DIR/issue-39362.rs:1:6
    |
 LL | enum Foo {
-   |      ---
+   |      ^^^
 LL |     Bar { bar: Bar, id: usize }
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr
index 4973e42b054..40b42af26b3 100644
--- a/tests/ui/pattern/usefulness/issue-40221.stderr
+++ b/tests/ui/pattern/usefulness/issue-40221.stderr
@@ -5,12 +5,12 @@ LL |     match proto {
    |           ^^^^^ pattern `P::C(PC::QA)` not covered
    |
 note: `P` defined here
-  --> $DIR/issue-40221.rs:2:5
+  --> $DIR/issue-40221.rs:1:6
    |
 LL | enum P {
-   |      -
+   |      ^
 LL |     C(PC),
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `P`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr
index b3e40b99239..50e13bdfdfe 100644
--- a/tests/ui/pattern/usefulness/issue-56379.stderr
+++ b/tests/ui/pattern/usefulness/issue-56379.stderr
@@ -5,16 +5,16 @@ LL |     match Foo::A(true) {
    |           ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered
    |
 note: `Foo` defined here
-  --> $DIR/issue-56379.rs:2:5
+  --> $DIR/issue-56379.rs:1:6
    |
 LL | enum Foo {
-   |      ---
+   |      ^^^
 LL |     A(bool),
-   |     ^ not covered
+   |     - not covered
 LL |     B(bool),
-   |     ^ not covered
+   |     - not covered
 LL |     C(bool),
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
index 5145f769075..1d1ea8e4964 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
@@ -1,10 +1,15 @@
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
 // Test the "defined here" and "not covered" diagnostic hints.
 // We also make sure that references are peeled off from the scrutinee type
 // so that the diagnostics work better with default binding modes.
 
 #[derive(Clone)]
 enum E {
-    //~^ NOTE
+    //~^ NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE
     //~| NOTE
     //~| NOTE
     //~| NOTE
@@ -12,10 +17,7 @@ enum E {
     //~| NOTE
     A,
     B,
-    //~^ NOTE `E` defined here
-    //~| NOTE `E` defined here
-    //~| NOTE `E` defined here
-    //~| NOTE  not covered
+    //~^ NOTE  not covered
     //~| NOTE  not covered
     //~| NOTE  not covered
     //~| NOTE  not covered
@@ -79,12 +81,12 @@ fn by_ref_thrice(e: & &mut &E) {
 }
 
 enum Opt {
-    //~^ NOTE
+    //~^ NOTE `Opt` defined here
+    //~| NOTE
     //~| NOTE
     Some(u8),
     None,
-    //~^ NOTE `Opt` defined here
-    //~| NOTE not covered
+    //~^ NOTE not covered
     //~| NOTE not covered
 }
 
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index 8489e2f14b8..a9e55fa53a6 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -1,20 +1,20 @@
 error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:35:11
+  --> $DIR/non-exhaustive-defined-here.rs:37:11
    |
 LL |     match e1 {
    |           ^^ patterns `E::B` and `E::C` not covered
    |
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -23,7 +23,7 @@ LL +         E::B | E::C => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/non-exhaustive-defined-here.rs:41:9
+  --> $DIR/non-exhaustive-defined-here.rs:43:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `E::B` and `E::C` not covered
@@ -31,7 +31,7 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:6:6
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
    |      ^
@@ -48,22 +48,22 @@ LL |     if let E::A = e { todo!() };
    |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:50:11
+  --> $DIR/non-exhaustive-defined-here.rs:52:11
    |
 LL |     match e {
    |           ^ patterns `&E::B` and `&E::C` not covered
    |
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `&E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -72,7 +72,7 @@ LL +         &E::B | &E::C => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/non-exhaustive-defined-here.rs:57:9
+  --> $DIR/non-exhaustive-defined-here.rs:59:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `&E::B` and `&E::C` not covered
@@ -80,7 +80,7 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:6:6
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
    |      ^
@@ -97,22 +97,22 @@ LL |     if let E::A = e { todo!() };
    |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:66:11
+  --> $DIR/non-exhaustive-defined-here.rs:68:11
    |
 LL |     match e {
    |           ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
    |
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `&&mut &E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -121,7 +121,7 @@ LL +         &&mut &E::B | &&mut &E::C => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/non-exhaustive-defined-here.rs:73:9
+  --> $DIR/non-exhaustive-defined-here.rs:75:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
@@ -129,7 +129,7 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:6:6
+  --> $DIR/non-exhaustive-defined-here.rs:8:6
    |
 LL | enum E {
    |      ^
@@ -146,19 +146,19 @@ LL |     if let E::A = e { todo!() };
    |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `Opt::None` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:92:11
+  --> $DIR/non-exhaustive-defined-here.rs:94:11
    |
 LL |     match e {
    |           ^ pattern `Opt::None` not covered
    |
 note: `Opt` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:85:5
+  --> $DIR/non-exhaustive-defined-here.rs:83:6
    |
 LL | enum Opt {
-   |      ---
+   |      ^^^
 ...
 LL |     None,
-   |     ^^^^ not covered
+   |     ---- not covered
    = note: the matched value is of type `Opt`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -167,7 +167,7 @@ LL +         Opt::None => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/non-exhaustive-defined-here.rs:99:9
+  --> $DIR/non-exhaustive-defined-here.rs:101:9
    |
 LL |     let Opt::Some(ref _x) = e;
    |         ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered
@@ -175,7 +175,7 @@ LL |     let Opt::Some(ref _x) = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Opt` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:81:6
+  --> $DIR/non-exhaustive-defined-here.rs:83:6
    |
 LL | enum Opt {
    |      ^^^
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
index 98e417a17f8..310049fe13e 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -18,10 +18,10 @@ LL |     match x {
    |           ^ pattern `T::A(U::C)` not covered
    |
 note: `T` defined here
-  --> $DIR/non-exhaustive-match-nested.rs:1:10
+  --> $DIR/non-exhaustive-match-nested.rs:1:6
    |
 LL | enum T { A(U), B }
-   |      -   ^ not covered
+   |      ^   - not covered
    = note: the matched value is of type `T`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
index e59e8885e1a..4bebd3cbbef 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -5,10 +5,10 @@ LL |     match x { T::B => { } }
    |           ^ pattern `T::A` not covered
    |
 note: `T` defined here
-  --> $DIR/non-exhaustive-match.rs:3:10
+  --> $DIR/non-exhaustive-match.rs:3:6
    |
 LL | enum T { A, B }
-   |      -   ^ not covered
+   |      ^   - not covered
    = note: the matched value is of type `T`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -79,10 +79,10 @@ LL |     match T::A {
    |           ^^^^ pattern `T::B` not covered
    |
 note: `T` defined here
-  --> $DIR/non-exhaustive-match.rs:3:13
+  --> $DIR/non-exhaustive-match.rs:3:6
    |
 LL | enum T { A, B }
-   |      -      ^ not covered
+   |      ^      - not covered
    = note: the matched value is of type `T`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
index f914b98d923..cceb1d8f65d 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
@@ -23,12 +23,12 @@ LL |     match Color::Red {
    |           ^^^^^^^^^^ pattern `Color::Red` not covered
    |
 note: `Color` defined here
-  --> $DIR/non-exhaustive-pattern-witness.rs:17:5
+  --> $DIR/non-exhaustive-pattern-witness.rs:16:6
    |
 LL | enum Color {
-   |      -----
+   |      ^^^^^
 LL |     Red,
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `Color`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -43,17 +43,17 @@ LL |     match Direction::North {
    |           ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered
    |
 note: `Direction` defined here
-  --> $DIR/non-exhaustive-pattern-witness.rs:32:5
+  --> $DIR/non-exhaustive-pattern-witness.rs:30:6
    |
 LL | enum Direction {
-   |      ---------
+   |      ^^^^^^^^^
 LL |     North,
 LL |     East,
-   |     ^^^^ not covered
+   |     ---- not covered
 LL |     South,
-   |     ^^^^^ not covered
+   |     ----- not covered
 LL |     West,
-   |     ^^^^ not covered
+   |     ---- not covered
    = note: the matched value is of type `Direction`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -72,6 +72,17 @@ note: `ExcessiveEnum` defined here
    |
 LL | enum ExcessiveEnum {
    |      ^^^^^^^^^^^^^
+LL |     First,
+LL |     Second,
+   |     ------ not covered
+LL |     Third,
+   |     ----- not covered
+LL |     Fourth,
+   |     ------ not covered
+LL |     Fifth,
+   |     ----- not covered
+LL |     Sixth,
+   |     ----- not covered
    = note: the matched value is of type `ExcessiveEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
@@ -86,13 +97,13 @@ LL |     match Color::Red {
    |           ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered
    |
 note: `Color` defined here
-  --> $DIR/non-exhaustive-pattern-witness.rs:19:5
+  --> $DIR/non-exhaustive-pattern-witness.rs:16:6
    |
 LL | enum Color {
-   |      -----
+   |      ^^^^^
 ...
 LL |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 },
-   |     ^^^^^^^^^^ not covered
+   |     ---------- not covered
    = note: the matched value is of type `Color`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
index f944c25a905..f75517fb791 100644
--- a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
+++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
@@ -5,13 +5,13 @@ LL |     match UnstableEnum::Stable {
    |           ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered
    |
 note: `UnstableEnum` defined here
-  --> $DIR/auxiliary/unstable.rs:9:5
+  --> $DIR/auxiliary/unstable.rs:5:1
    |
 LL | pub enum UnstableEnum {
-   | ---------------------
+   | ^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     Stable2,
-   |     ^^^^^^^ not covered
+   |     ------- not covered
    = note: the matched value is of type `UnstableEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
index 22425aa0dd4..3d2b540a9f5 100644
--- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
+++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
@@ -5,12 +5,12 @@ LL |     match x {
    |           ^ pattern `A::B { x: Some(_) }` not covered
    |
 note: `A` defined here
-  --> $DIR/struct-like-enum-nonexhaustive.rs:2:5
+  --> $DIR/struct-like-enum-nonexhaustive.rs:1:6
    |
 LL | enum A {
-   |      -
+   |      ^
 LL |     B { x: Option<isize> },
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `A`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
index d776249b231..4a4945156f7 100644
--- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
+++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
@@ -5,13 +5,13 @@ LL |     match UnstableEnum::Stable {
    |           ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered
    |
 note: `UnstableEnum` defined here
-  --> $DIR/auxiliary/unstable.rs:11:5
+  --> $DIR/auxiliary/unstable.rs:5:1
    |
 LL | pub enum UnstableEnum {
-   | ---------------------
+   | ^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     Unstable,
-   |     ^^^^^^^^ not covered
+   |     -------- not covered
    = note: the matched value is of type `UnstableEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/tests/ui/resolve/fn-new-doesnt-exist.rs b/tests/ui/resolve/fn-new-doesnt-exist.rs
new file mode 100644
index 00000000000..4f6290808fc
--- /dev/null
+++ b/tests/ui/resolve/fn-new-doesnt-exist.rs
@@ -0,0 +1,5 @@
+use std::net::TcpStream;
+
+fn main() {
+   let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found
+}
diff --git a/tests/ui/resolve/fn-new-doesnt-exist.stderr b/tests/ui/resolve/fn-new-doesnt-exist.stderr
new file mode 100644
index 00000000000..39adc0fde44
--- /dev/null
+++ b/tests/ui/resolve/fn-new-doesnt-exist.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
+  --> $DIR/fn-new-doesnt-exist.rs:4:28
+   |
+LL |    let stream = TcpStream::new();
+   |                            ^^^ function or associated item not found in `TcpStream`
+   |
+note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
+      TcpStream::connect
+      TcpStream::connect_timeout
+  --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr
index 730fd6d6026..9d0439d9d87 100644
--- a/tests/ui/resolve/issue-82865.stderr
+++ b/tests/ui/resolve/issue-82865.stderr
@@ -15,6 +15,13 @@ LL |     Box::z
 LL |     mac!();
    |     ------ in this macro invocation
    |
+note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
+      Box::<T>::new
+      Box::<T>::new_uninit
+      Box::<T>::new_zeroed
+      Box::<T>::try_new
+      and 18 others
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
index de1bf8be885..7386f10a6fb 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -17,18 +17,18 @@ LL |     match NonExhaustiveEnum::Unit {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
    |
 note: `NonExhaustiveEnum` defined here
-  --> $DIR/enum_same_crate_empty_match.rs:5:5
+  --> $DIR/enum_same_crate_empty_match.rs:4:10
    |
 LL | pub enum NonExhaustiveEnum {
-   |          -----------------
+   |          ^^^^^^^^^^^^^^^^^
 LL |     Unit,
-   |     ^^^^ not covered
+   |     ---- not covered
 LL |
 LL |     Tuple(u32),
-   |     ^^^^^ not covered
+   |     ----- not covered
 LL |
 LL |     Struct { field: u32 }
-   |     ^^^^^^ not covered
+   |     ------ not covered
    = note: the matched value is of type `NonExhaustiveEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
@@ -44,18 +44,18 @@ LL |     match NormalEnum::Unit {}
    |           ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered
    |
 note: `NormalEnum` defined here
-  --> $DIR/enum_same_crate_empty_match.rs:14:5
+  --> $DIR/enum_same_crate_empty_match.rs:13:10
    |
 LL | pub enum NormalEnum {
-   |          ----------
+   |          ^^^^^^^^^^
 LL |     Unit,
-   |     ^^^^ not covered
+   |     ---- not covered
 LL |
 LL |     Tuple(u32),
-   |     ^^^^^ not covered
+   |     ----- not covered
 LL |
 LL |     Struct { field: u32 }
-   |     ^^^^^^ not covered
+   |     ------ not covered
    = note: the matched value is of type `NormalEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr
new file mode 100644
index 00000000000..9192c66143c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr
@@ -0,0 +1,75 @@
+error: some variants are not matched explicitly
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11
+   |
+LL |     match val {
+   |           ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+   |
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:23:11
+   |
+LL |     match val {
+   |           ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+   |
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:22:27
+   |
+LL |     #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the lint level must be set on the whole match
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ------------------------------- remove this attribute
+LL |         _ => {}
+   |         ^
+   |
+   = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+   |
+LL +     #[deny(non_exhaustive_omitted_patterns)]
+LL |     match val {
+   |
+
+warning: the lint level must be set on the whole match
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9
+   |
+LL |         #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+   |                               ------------------------------- remove this attribute
+LL |         _ => {}
+   |         ^
+   |
+   = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+   |
+LL +     #[deny(non_exhaustive_omitted_patterns)]
+LL |     match val {
+   |
+
+warning: the lint level must be set on the whole match
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9
+   |
+LL |         #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
+   |                               ------------------------------- remove this attribute
+LL |         _ => {}
+   |         ^
+   |
+   = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+   |
+LL +     #[warn(non_exhaustive_omitted_patterns)]
+LL |     match val {
+   |
+
+error: aborting due to 2 previous errors; 3 warnings emitted
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr
new file mode 100644
index 00000000000..46093eb9fb3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr
@@ -0,0 +1,31 @@
+error: some variants are not matched explicitly
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11
+   |
+LL |     match val {
+   |           ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+   |
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the lint level must be set on the whole match
+  --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ------------------------------- remove this attribute
+LL |         _ => {}
+   |         ^
+   |
+   = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+   |
+LL +     #[deny(non_exhaustive_omitted_patterns)]
+LL |     match val {
+   |
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs
new file mode 100644
index 00000000000..33f9f56a5bb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs
@@ -0,0 +1,53 @@
+// revisions: normal lint
+// Test that putting the lint level on a match arm emits a warning, as this was previously
+// meaningful and is no longer.
+#![feature(non_exhaustive_omitted_patterns_lint)]
+
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let val = NonExhaustiveEnum::Unit;
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match val {
+        //~^ ERROR some variants are not matched explicitly
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        _ => {}
+    }
+
+    #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+    match val {
+        //[lint]~^ ERROR some variants are not matched explicitly
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        _ => {}
+    }
+
+    match val {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ WARN lint level must be set on the whole match
+
+    match val {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+        _ => {}
+    }
+    //[lint]~^^ WARN lint level must be set on the whole match
+
+    match val {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
+        _ => {}
+    }
+    //[lint]~^^ WARN lint level must be set on the whole match
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
index a9c54af0418..c125756a646 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -62,14 +62,14 @@ LL |     match x {}
    |           ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
    |
 note: `UninhabitedVariants` defined here
-  --> $DIR/auxiliary/uninhabited.rs:17:23
+  --> $DIR/auxiliary/uninhabited.rs:16:1
    |
 LL | pub enum UninhabitedVariants {
-   | ----------------------------
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     #[non_exhaustive] Tuple(!),
-   |                       ^^^^^ not covered
+   |                       ----- not covered
 LL |     #[non_exhaustive] Struct { x: ! }
-   |                       ^^^^^^ not covered
+   |                       ------ not covered
    = note: the matched value is of type `UninhabitedVariants`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
index ec2a2f6f055..7a12aca8520 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
@@ -43,14 +43,14 @@ LL |     match x {}
    |           ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
    |
 note: `UninhabitedVariants` defined here
-  --> $DIR/match_same_crate.rs:16:23
+  --> $DIR/match_same_crate.rs:15:10
    |
 LL | pub enum UninhabitedVariants {
-   |          -------------------
+   |          ^^^^^^^^^^^^^^^^^^^
 LL |     #[non_exhaustive] Tuple(!),
-   |                       ^^^^^ not covered
+   |                       ----- not covered
 LL |     #[non_exhaustive] Struct { x: ! }
-   |                       ^^^^^^ not covered
+   |                       ------ not covered
    = note: the matched value is of type `UninhabitedVariants`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
index b6b777ec56c..19e2546b0da 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -62,14 +62,14 @@ LL |     match x {}
    |           ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
    |
 note: `UninhabitedVariants` defined here
-  --> $DIR/auxiliary/uninhabited.rs:17:23
+  --> $DIR/auxiliary/uninhabited.rs:16:1
    |
 LL | pub enum UninhabitedVariants {
-   | ----------------------------
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     #[non_exhaustive] Tuple(!),
-   |                       ^^^^^ not covered
+   |                       ----- not covered
 LL |     #[non_exhaustive] Struct { x: ! }
-   |                       ^^^^^^ not covered
+   |                       ------ not covered
    = note: the matched value is of type `UninhabitedVariants`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs
new file mode 100644
index 00000000000..6598d1da0f8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs
@@ -0,0 +1,15 @@
+#![feature(const_closures, const_trait_impl, effects)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl Foo for () {
+    fn foo(&self) {}
+}
+
+fn main() {
+    (const || { (()).foo() })();
+    //~^ ERROR: cannot call non-const fn
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr
new file mode 100644
index 00000000000..002d586ac64
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions
+  --> $DIR/const_closure-const_trait_impl-ice-113381.rs:13:22
+   |
+LL |     (const || { (()).foo() })();
+   |                      ^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs
new file mode 100644
index 00000000000..1954d2942e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds
+
+#![allow(incomplete_features, unused)]
+#![feature(effects, adt_const_params)]
+
+struct Bar<T>(T);
+
+impl<T> Bar<T> {
+    const fn value() -> usize {
+        42
+    }
+}
+
+struct Foo<const N: [u8; Bar::<u32>::value()]>;
+
+pub fn main() {}
diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr
index b612fdf16fc..457870821a1 100644
--- a/tests/ui/span/issue-37767.stderr
+++ b/tests/ui/span/issue-37767.stderr
@@ -16,12 +16,12 @@ LL |     fn foo(&mut self) {}
    |     ^^^^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(&a)
-   |     ~~~~~~~~~~
+LL |     A::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(&a)
-   |     ~~~~~~~~~~
+LL |     B::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/issue-37767.rs:22:7
diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr
index 1cc37d61151..0372a7e6cc0 100644
--- a/tests/ui/suggestions/deref-path-method.stderr
+++ b/tests/ui/suggestions/deref-path-method.stderr
@@ -4,6 +4,13 @@ error[E0599]: no function or associated item named `contains` found for struct `
 LL |     Vec::contains(&vec, &0);
    |          ^^^^^^^^ function or associated item not found in `Vec<_, _>`
    |
+note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions:
+      Vec::<T>::new
+      Vec::<T>::with_capacity
+      Vec::<T>::from_raw_parts
+      Vec::<T, A>::new_in
+      and 2 others
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: the function `contains` is implemented on `[_]`
    |
 LL |     <[_]>::contains(&vec, &0);
diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr
index 4ef5948d9bf..644841fdf7e 100644
--- a/tests/ui/suggestions/issue-109291.stderr
+++ b/tests/ui/suggestions/issue-109291.stderr
@@ -6,6 +6,13 @@ LL |     println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capt
    |                                                                 |
    |                                                                 function or associated item not found in `Backtrace`
    |                                                                 help: there is an associated function with a similar name: `force_capture`
+   |
+note: if you're trying to build a new `Backtrace` consider using one of the following associated functions:
+      Backtrace::capture
+      Backtrace::force_capture
+      Backtrace::disabled
+      Backtrace::create
+  --> $SRC_DIR/std/src/backtrace.rs:LL:COL
 
 error: aborting due to previous error
 
diff --git a/tests/ui/target-feature/similar-feature-suggestion.stderr b/tests/ui/target-feature/similar-feature-suggestion.stderr
index 2f376065fdf..f39dfd401e0 100644
--- a/tests/ui/target-feature/similar-feature-suggestion.stderr
+++ b/tests/ui/target-feature/similar-feature-suggestion.stderr
@@ -1,6 +1,6 @@
-warning: unknown feature specified for `-Ctarget-feature`: `rdrnd`
+warning: unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd`
    |
-   = note: it is still passed through to the codegen backend
+   = note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
    = help: you might have meant: `rdrand`
 
 warning: 1 warning emitted
diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs
new file mode 100644
index 00000000000..bd0d72938f4
--- /dev/null
+++ b/tests/ui/target-feature/unstable-feature.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Ctarget-feature=+vaes --crate-type=rlib --target=x86_64-unknown-linux-gnu
+// build-pass
+// needs-llvm-components: x86
+
+#![feature(no_core)]
+#![no_core]
diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr
new file mode 100644
index 00000000000..d34544c5c27
--- /dev/null
+++ b/tests/ui/target-feature/unstable-feature.stderr
@@ -0,0 +1,6 @@
+warning: unstable feature specified for `-Ctarget-feature`: `vaes`
+   |
+   = note: this feature is not stably supported; its behavior can change in the future
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr
index 712050a25fc..607d7ee902c 100644
--- a/tests/ui/thread-local/thread-local-static.stderr
+++ b/tests/ui/thread-local/thread-local-static.mir.stderr
@@ -1,5 +1,5 @@
 error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/thread-local-static.rs:7:12
+  --> $DIR/thread-local-static.rs:10:12
    |
 LL | const fn g(x: &mut [u32; 8]) {
    |            ^
@@ -8,13 +8,13 @@ LL | const fn g(x: &mut [u32; 8]) {
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-static.rs:9:28
+  --> $DIR/thread-local-static.rs:12:28
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                            ^^^^^^^^^^^^
 
 error[E0013]: constant functions cannot refer to statics
-  --> $DIR/thread-local-static.rs:9:28
+  --> $DIR/thread-local-static.rs:12:28
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                            ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/thread-local-static.rs:9:23
+  --> $DIR/thread-local-static.rs:12:23
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                       ^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/thread-local-static.rs:9:23
+  --> $DIR/thread-local-static.rs:12:23
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                       ^^^^^^^^^^^^^^^^^ use of mutable static
diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs
index c7fee9e6b4c..afaffbb7e9b 100644
--- a/tests/ui/thread-local/thread-local-static.rs
+++ b/tests/ui/thread-local/thread-local-static.rs
@@ -1,7 +1,10 @@
 // edition:2018
+// revisions: mir thir
+//thir: -Zthir-unsafeck
 
 #![feature(thread_local)]
 #![feature(const_swap)]
+
 #[thread_local]
 static mut STATIC_VAR_2: [u32; 8] = [4; 8];
 const fn g(x: &mut [u32; 8]) {
diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr
new file mode 100644
index 00000000000..607d7ee902c
--- /dev/null
+++ b/tests/ui/thread-local/thread-local-static.thir.stderr
@@ -0,0 +1,44 @@
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:10:12
+   |
+LL | const fn g(x: &mut [u32; 8]) {
+   |            ^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+
+error[E0013]: constant functions cannot refer to statics
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0013, E0133, E0625, E0658.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs
index f6b19e7adf5..fac7d76f8cf 100644
--- a/tests/ui/traits/new-solver/specialization-transmute.rs
+++ b/tests/ui/traits/new-solver/specialization-transmute.rs
@@ -10,7 +10,7 @@ trait Default {
 }
 
 impl<T> Default for T {
-    default type Id = T;
+    default type Id = T; //~ ERROR type annotations needed
     // This will be fixed by #111994
     fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed
         self
diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr
index 09b1405fefb..18965a465b3 100644
--- a/tests/ui/traits/new-solver/specialization-transmute.stderr
+++ b/tests/ui/traits/new-solver/specialization-transmute.stderr
@@ -16,6 +16,13 @@ LL |     fn intu(&self) -> &Self::Id {
    |
    = note: cannot satisfy `<T as Default>::Id == _`
 
-error: aborting due to previous error; 1 warning emitted
+error[E0282]: type annotations needed
+  --> $DIR/specialization-transmute.rs:13:23
+   |
+LL |     default type Id = T;
+   |                       ^ cannot infer type for associated type `<T as Default>::Id`
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0284`.
+Some errors have detailed explanations: E0282, E0284.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs
index 02150689ee5..7fd753109be 100644
--- a/tests/ui/traits/new-solver/specialization-unconstrained.rs
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs
@@ -11,7 +11,7 @@ trait Default {
 }
 
 impl<T> Default for T {
-   default type Id = T;
+   default type Id = T; //~ ERROR type annotations needed
 }
 
 fn test<T: Default<Id = U>, U>() {}
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
index 910925cbaeb..ed4dafa1484 100644
--- a/tests/ui/traits/new-solver/specialization-unconstrained.stderr
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
@@ -20,6 +20,13 @@ note: required by a bound in `test`
 LL | fn test<T: Default<Id = U>, U>() {}
    |                    ^^^^^^ required by this bound in `test`
 
-error: aborting due to previous error; 1 warning emitted
+error[E0282]: type annotations needed
+  --> $DIR/specialization-unconstrained.rs:14:22
+   |
+LL |    default type Id = T;
+   |                      ^ cannot infer type for associated type `<T as Default>::Id`
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0284`.
+Some errors have detailed explanations: E0282, E0284.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
new file mode 100644
index 00000000000..9f373cc50f0
--- /dev/null
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
new file mode 100644
index 00000000000..9f373cc50f0
--- /dev/null
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
new file mode 100644
index 00000000000..9a8a5ced2e2
--- /dev/null
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
@@ -0,0 +1,16 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete and may not be safe
+
+fn trivial<A>()
+where
+    for<B> dyn Fn(A, *const B): Fn(A, *const B),
+{
+}
+
+fn main() {
+    trivial::<u8>();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs
new file mode 100644
index 00000000000..b999f251d33
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+trait Foo {
+    type Bar<T>
+    where
+        dyn Send + 'static: Send;
+}
+
+impl Foo for () {
+    type Bar<T> = i32;
+    // We take `<() as Foo>::Bar<T>: Sized` and normalize it under the where clause
+    // of `for<S> <() as Foo>::Bar<S> = i32`. This gives us back `i32: Send` with
+    // the nested obligation `(dyn Send + 'static): Send`. However, during candidate
+    // assembly for object types, we disqualify any obligations that has non-region
+    // late-bound vars in the param env(!), rather than just the predicate. This causes
+    // the where clause to not hold even though it trivially should.
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout
index ce90c76217b..b43e168df3f 100644
--- a/tests/ui/traits/object/print_vtable_sizes.stdout
+++ b/tests/ui/traits/object/print_vtable_sizes.stdout
@@ -1,11 +1,11 @@
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
+print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr
index 544213dbc55..15f059ffa48 100644
--- a/tests/ui/union/union-unsafe.mir.stderr
+++ b/tests/ui/union/union-unsafe.mir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:33:5
+  --> $DIR/union-unsafe.rs:34:5
    |
 LL |     *(u.p) = 13;
    |     ^^^^^^^^^^^ access to union field
@@ -7,7 +7,7 @@ LL |     *(u.p) = 13;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:46:6
+  --> $DIR/union-unsafe.rs:47:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -15,7 +15,7 @@ LL |     *u3.a = T::default();
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:52:6
+  --> $DIR/union-unsafe.rs:53:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -23,7 +23,7 @@ LL |     *u3.a = T::default();
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:60:13
+  --> $DIR/union-unsafe.rs:61:13
    |
 LL |     let a = u1.a;
    |             ^^^^ access to union field
@@ -31,7 +31,7 @@ LL |     let a = u1.a;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:63:14
+  --> $DIR/union-unsafe.rs:64:14
    |
 LL |     let U1 { a } = u1;
    |              ^ access to union field
@@ -39,7 +39,7 @@ LL |     let U1 { a } = u1;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:64:12
+  --> $DIR/union-unsafe.rs:65:12
    |
 LL |     if let U1 { a: 12 } = u1 {}
    |            ^^^^^^^^^^^^ access to union field
@@ -47,7 +47,15 @@ LL |     if let U1 { a: 12 } = u1 {}
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:69:6
+  --> $DIR/union-unsafe.rs:66:12
+   |
+LL |     if let Some(U1 { a: 13 }) = Some(u1) {}
+   |            ^^^^^^^^^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:71:6
    |
 LL |     *u2.a = String::from("new");
    |      ^^^^ access to union field
@@ -55,7 +63,7 @@ LL |     *u2.a = String::from("new");
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:73:6
+  --> $DIR/union-unsafe.rs:75:6
    |
 LL |     *u3.a = 1;
    |      ^^^^ access to union field
@@ -63,13 +71,13 @@ LL |     *u3.a = 1;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:77:6
+  --> $DIR/union-unsafe.rs:79:6
    |
 LL |     *u3.a = String::from("new");
    |      ^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs
index 5e1837a901d..d1465486f77 100644
--- a/tests/ui/union/union-unsafe.rs
+++ b/tests/ui/union/union-unsafe.rs
@@ -1,30 +1,31 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
-use std::mem::ManuallyDrop;
 use std::cell::RefCell;
+use std::mem::ManuallyDrop;
 
 union U1 {
-    a: u8
+    a: u8,
 }
 
 union U2 {
-    a: ManuallyDrop<String>
+    a: ManuallyDrop<String>,
 }
 
 union U3<T> {
-    a: ManuallyDrop<T>
+    a: ManuallyDrop<T>,
 }
 
 union U4<T: Copy> {
-    a: T
+    a: T,
 }
 
 union URef {
     p: &'static mut i32,
 }
 
-union URefCell { // field that does not drop but is not `Copy`, either
+union URefCell {
+    // field that does not drop but is not `Copy`, either
     a: (ManuallyDrop<RefCell<i32>>, i32),
 }
 
@@ -62,6 +63,7 @@ fn main() {
 
     let U1 { a } = u1; //~ ERROR access to union field is unsafe
     if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
+    if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe
     // let U1 { .. } = u1; // OK
 
     let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK
diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr
index f959fe5bdb5..9ce835497c5 100644
--- a/tests/ui/union/union-unsafe.thir.stderr
+++ b/tests/ui/union/union-unsafe.thir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:33:6
+  --> $DIR/union-unsafe.rs:34:6
    |
 LL |     *(u.p) = 13;
    |      ^^^^^ access to union field
@@ -7,7 +7,7 @@ LL |     *(u.p) = 13;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:46:6
+  --> $DIR/union-unsafe.rs:47:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -15,7 +15,7 @@ LL |     *u3.a = T::default();
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:52:6
+  --> $DIR/union-unsafe.rs:53:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -23,7 +23,7 @@ LL |     *u3.a = T::default();
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:60:13
+  --> $DIR/union-unsafe.rs:61:13
    |
 LL |     let a = u1.a;
    |             ^^^^ access to union field
@@ -31,7 +31,7 @@ LL |     let a = u1.a;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:63:14
+  --> $DIR/union-unsafe.rs:64:14
    |
 LL |     let U1 { a } = u1;
    |              ^ access to union field
@@ -39,15 +39,23 @@ LL |     let U1 { a } = u1;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:64:8
+  --> $DIR/union-unsafe.rs:65:20
    |
 LL |     if let U1 { a: 12 } = u1 {}
-   |        ^^^^^^^^^^^^^^^^^^^^^ access to union field
+   |                    ^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:69:6
+  --> $DIR/union-unsafe.rs:66:25
+   |
+LL |     if let Some(U1 { a: 13 }) = Some(u1) {}
+   |                         ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:71:6
    |
 LL |     *u2.a = String::from("new");
    |      ^^^^ access to union field
@@ -55,7 +63,7 @@ LL |     *u2.a = String::from("new");
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:73:6
+  --> $DIR/union-unsafe.rs:75:6
    |
 LL |     *u3.a = 1;
    |      ^^^^ access to union field
@@ -63,13 +71,13 @@ LL |     *u3.a = 1;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:77:6
+  --> $DIR/union-unsafe.rs:79:6
    |
 LL |     *u3.a = String::from("new");
    |      ^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr
index fbc621f4d0e..ea53bf59d31 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr
@@ -1,12 +1,12 @@
 warning: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:5
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:11:1
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1
    |
 LL | unsafe fn foo() {
    | ^^^^^^^^^^^^^^^
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
index a192f3445f7..1b429955cb0 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
@@ -1,17 +1,21 @@
 // edition: 2024
 // compile-flags: -Zunstable-options
 // check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![crate_type = "lib"]
-
 #![deny(unused_unsafe)]
 
 unsafe fn unsf() {}
 
 unsafe fn foo() {
     unsf();
-    //~^ WARN call to unsafe function is unsafe and requires unsafe block
+    //[mir]~^ WARN call to unsafe function is unsafe and requires unsafe block
+    //[thir]~^^ WARN call to unsafe function `unsf` is unsafe and requires unsafe block
 
     // no unused_unsafe
-    unsafe { unsf(); }
+    unsafe {
+        unsf();
+    }
 }
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr
new file mode 100644
index 00000000000..d63843ed2b3
--- /dev/null
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr
@@ -0,0 +1,16 @@
+warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1
+   |
+LL | unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^
+   = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
index 427843f8d45..dc6bd72f56c 100644
--- a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
+++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
@@ -6,6 +6,14 @@ LL |     let y = &mut x.0;
    |
    = note: mutating layout constrained fields cannot statically be checked for valid values
 
-error: aborting due to previous error
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:12:25
+   |
+LL |     if let Some(NonZero(ref mut y)) = Some(x) {}
+   |                         ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs
index 9a6bb18f926..ad9d598aba2 100644
--- a/tests/ui/unsafe/ranged_ints2.rs
+++ b/tests/ui/unsafe/ranged_ints2.rs
@@ -9,4 +9,5 @@ pub(crate) struct NonZero<T>(pub(crate) T);
 fn main() {
     let mut x = unsafe { NonZero(1) };
     let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
+    if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe
 }
diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
index 427843f8d45..dc6bd72f56c 100644
--- a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
+++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
@@ -6,6 +6,14 @@ LL |     let y = &mut x.0;
    |
    = note: mutating layout constrained fields cannot statically be checked for valid values
 
-error: aborting due to previous error
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:12:25
+   |
+LL |     if let Some(NonZero(ref mut y)) = Some(x) {}
+   |                         ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
index 4cdd97e5e06..ad0621a1d04 100644
--- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
+++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
@@ -5,6 +5,11 @@ LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:1
+   |
+LL | unsafe fn deny_level() {
+   | ^^^^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
    |
@@ -46,6 +51,11 @@ LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:1
+   |
+LL | unsafe fn warning_level() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
    |
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed
index db1c102210e..b59029df642 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed
@@ -1,7 +1,10 @@
 // run-rustfix
 // aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
 
 extern crate external_unsafe_macro;
 
@@ -9,11 +12,13 @@ unsafe fn unsf() {}
 
 pub unsafe fn foo() { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
 }}
 
@@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe {
 }}
 
 macro_rules! unsafe_macro { () => (unsf()) }
-//~^ ERROR call to unsafe function is unsafe
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
-//~| ERROR call to unsafe function is unsafe
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
 
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr
index 43f619c27d2..7a1b83c7367 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr
@@ -1,23 +1,23 @@
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:12:5
+  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:10:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:13:1
    |
 LL | pub unsafe fn foo() {
    | ^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
-  --> $DIR/wrapping-unsafe-block-sugg.rs:4:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:6:9
    |
 LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
+  --> $DIR/wrapping-unsafe-block-sugg.rs:19:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
@@ -25,20 +25,20 @@ LL |     unsf();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:22:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:27:13
    |
 LL |     let y = *x;
    |             ^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:20:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:25:1
    |
 LL | pub unsafe fn bar(x: *const i32) -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:25:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:30:9
    |
 LL |     y + *x
    |         ^^ dereference of raw pointer
@@ -46,20 +46,20 @@ LL |     y + *x
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:33:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
    |
 LL |     let y = BAZ;
    |             ^^^ use of mutable static
    |
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:31:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:36:1
    |
 LL | pub unsafe fn baz() -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:36:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:41:9
    |
 LL |     y + BAZ
    |         ^^^ use of mutable static
@@ -67,7 +67,7 @@ LL |     y + BAZ
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:41:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
@@ -77,14 +77,14 @@ LL |     unsafe_macro!();
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:49:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:56:1
    |
 LL | pub unsafe fn unsafe_in_macro() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:41:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
index 9c6be45896e..3629b8a1beb 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
@@ -1,7 +1,10 @@
 // run-rustfix
 // aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
 
 extern crate external_unsafe_macro;
 
@@ -9,11 +12,13 @@ unsafe fn unsf() {}
 
 pub unsafe fn foo() {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
 }
 
@@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 {
 }
 
 macro_rules! unsafe_macro { () => (unsf()) }
-//~^ ERROR call to unsafe function is unsafe
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
-//~| ERROR call to unsafe function is unsafe
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
 
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed
new file mode 100644
index 00000000000..b59029df642
--- /dev/null
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed
@@ -0,0 +1,73 @@
+// run-rustfix
+// aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
+
+extern crate external_unsafe_macro;
+
+unsafe fn unsf() {}
+
+pub unsafe fn foo() { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
+    //~| NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
+    //~| NOTE
+}}
+
+pub unsafe fn bar(x: *const i32) -> i32 { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+    y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+}}
+
+static mut BAZ: i32 = 0;
+pub unsafe fn baz() -> i32 { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+    y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+}}
+
+macro_rules! unsafe_macro { () => (unsf()) }
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
+//~| NOTE
+//~| NOTE
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
+//~| NOTE
+//~| NOTE
+
+pub unsafe fn unsafe_in_macro() { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    unsafe_macro!();
+    //~^ NOTE
+    //~| NOTE
+    unsafe_macro!();
+    //~^ NOTE
+    //~| NOTE
+}}
+
+pub unsafe fn unsafe_in_external_macro() {
+    // FIXME: https://github.com/rust-lang/rust/issues/112504
+    // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    external_unsafe_macro::unsafe_macro!();
+    external_unsafe_macro::unsafe_macro!();
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr
new file mode 100644
index 00000000000..b1fb35f85a6
--- /dev/null
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr
@@ -0,0 +1,99 @@
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:13:1
+   |
+LL | pub unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/wrapping-unsafe-block-sugg.rs:6:9
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:19:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:27:13
+   |
+LL |     let y = *x;
+   |             ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:25:1
+   |
+LL | pub unsafe fn bar(x: *const i32) -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:30:9
+   |
+LL |     y + *x
+   |         ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
+   |
+LL |     let y = BAZ;
+   |             ^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:36:1
+   |
+LL | pub unsafe fn baz() -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:41:9
+   |
+LL |     y + BAZ
+   |         ^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
+   |
+LL | macro_rules! unsafe_macro { () => (unsf()) }
+   |                                    ^^^^^^ call to unsafe function
+...
+LL |     unsafe_macro!();
+   |     --------------- in this macro invocation
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:56:1
+   |
+LL | pub unsafe fn unsafe_in_macro() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
+   |
+LL | macro_rules! unsafe_macro { () => (unsf()) }
+   |                                    ^^^^^^ call to unsafe function
+...
+LL |     unsafe_macro!();
+   |     --------------- in this macro invocation
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
diff --git a/triagebot.toml b/triagebot.toml
index b419727bcfd..69bbbdb03bf 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -415,7 +415,7 @@ Issue #{number} "{title}" has been added.
 """
 
 [no-merges]
-exclude_titles = ["Rollup of", "subtree update"]
+exclude_titles = ["Rollup of", "subtree update", "Subtree update"]
 labels = ["has-merge-commits", "S-waiting-on-author"]
 
 [github-releases]
@@ -608,19 +608,18 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin", "oli-obk"]
+users_on_vacation = ["jyn514", "WaffleLapkin", "oli-obk"]
 
 [assign.adhoc_groups]
 compiler-team = [
     "@cjgillot",
+    "@compiler-errors",
     "@petrochenkov",
     "@davidtwco",
     "@oli-obk",
     "@wesleywiser",
 ]
 compiler-team-contributors = [
-    "@compiler-errors",
-    "@jackh726",
     "@TaKO8Ki",
     "@WaffleLapkin",
     "@b-naber",