about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--Cargo.lock205
-rw-r--r--Cargo.toml1
-rw-r--r--compiler/rustc_abi/src/callconv.rs2
-rw-r--r--compiler/rustc_abi/src/layout.rs23
-rw-r--r--compiler/rustc_abi/src/lib.rs35
-rw-r--r--compiler/rustc_ast_ir/src/lib.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs34
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs3
-rw-r--r--compiler/rustc_borrowck/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs57
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs63
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/comments.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs38
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs129
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs40
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs19
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs16
-rw-r--r--compiler/rustc_data_structures/src/intern.rs5
-rw-r--r--compiler/rustc_driver_impl/src/signal_handler.rs50
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0803.md46
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs64
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs54
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs136
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs3
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs6
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/messages.ftl28
-rw-r--r--compiler/rustc_middle/src/error.rs10
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs89
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs405
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs416
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs312
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/thir.rs1
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs36
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs3
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs1
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs11
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs51
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs19
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs6
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs5
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs186
-rw-r--r--compiler/rustc_mir_transform/src/patch.rs51
-rw-r--r--compiler/rustc_mir_transform/src/single_use_consts.rs8
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs5
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/alias_relate.rs12
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs37
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs5
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs16
-rw-r--r--compiler/rustc_passes/src/check_attr.rs47
-rw-r--r--compiler/rustc_resolve/src/imports.rs13
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs88
-rw-r--r--compiler/rustc_resolve/src/lib.rs26
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs9
-rw-r--r--compiler/rustc_target/src/callconv/loongarch.rs2
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs123
-rw-r--r--compiler/rustc_target/src/callconv/riscv.rs2
-rw-r--r--compiler/rustc_target/src/callconv/x86.rs18
-rw-r--r--compiler/rustc_target/src/callconv/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/callconv/x86_win64.rs18
-rw-r--r--compiler/rustc_target/src/spec/base/avr.rs (renamed from compiler/rustc_target/src/spec/base/avr_gnu.rs)40
-rw-r--r--compiler/rustc_target/src/spec/base/mod.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs31
-rw-r--r--compiler/rustc_target/src/spec/targets/avr_none.rs32
-rw-r--r--compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs (renamed from compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs)0
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs69
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs11
-rw-r--r--compiler/rustc_transmute/Cargo.toml2
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml1
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs6
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs146
-rw-r--r--compiler/rustc_ty_utils/src/layout/invariant.rs15
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs3
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs15
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/visit.rs11
-rw-r--r--compiler/rustc_type_ir_macros/src/lib.rs6
-rw-r--r--compiler/stable_mir/src/abi.rs6
-rw-r--r--config.example.toml4
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/string.rs26
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/str.rs5
-rw-r--r--library/core/src/char/methods.rs11
-rw-r--r--library/core/src/char/mod.rs10
-rw-r--r--library/core/src/fmt/mod.rs6
-rw-r--r--library/core/src/iter/adapters/zip.rs8
-rw-r--r--library/core/src/num/int_macros.rs4
-rw-r--r--library/core/src/num/mod.rs8
-rw-r--r--library/core/src/num/nonzero.rs8
-rw-r--r--library/core/src/num/uint_macros.rs5
-rw-r--r--library/core/src/slice/iter/macros.rs35
-rw-r--r--library/core/src/slice/mod.rs4
-rw-r--r--library/core/src/slice/sort/shared/smallsort.rs31
-rw-r--r--library/core/src/str/mod.rs27
-rw-r--r--library/core/src/str/pattern.rs5
-rw-r--r--library/core/src/ub_checks.rs6
-rw-r--r--library/coretests/tests/char.rs3
-rw-r--r--library/coretests/tests/lib.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/masks.rs13
-rw-r--r--library/portable-simd/crates/core_simd/src/masks/full_masks.rs5
-rw-r--r--library/portable-simd/crates/core_simd/src/ops.rs1
-rw-r--r--library/portable-simd/crates/core_simd/src/ops/deref.rs3
-rw-r--r--library/portable-simd/crates/core_simd/src/ops/unary.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/simd/num/float.rs1
-rw-r--r--library/std/src/f16.rs2
-rw-r--r--library/std/src/fs.rs112
-rw-r--r--library/std/src/fs/tests.rs7
-rw-r--r--library/std/src/io/stdio.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/wasi/fs.rs11
-rw-r--r--library/std/src/panic.rs1
-rw-r--r--library/std/src/process.rs4
-rw-r--r--library/std/src/sys/os_str/bytes.rs86
-rw-r--r--library/std/src/sys/os_str/wtf8.rs107
-rw-r--r--library/std/src/sys/pal/windows/c.rs4
-rw-r--r--library/std/src/sys/pal/windows/stdio.rs3
-rw-r--r--library/std/src/sys/random/windows.rs2
-rw-r--r--library/std/src/sys/sync/mutex/windows7.rs2
-rw-r--r--library/std/src/sys/sync/thread_parking/windows7.rs8
-rw-r--r--library/std/src/sys_common/wtf8.rs76
-rw-r--r--library/std/src/time.rs10
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs83
-rw-r--r--src/bootstrap/src/core/build_steps/setup/tests.rs21
-rw-r--r--src/bootstrap/src/utils/proc_macro_deps.rs15
-rwxr-xr-xsrc/ci/docker/run.sh10
-rw-r--r--src/ci/docker/scripts/sccache.sh4
-rwxr-xr-xsrc/ci/run.sh2
-rwxr-xr-xsrc/ci/scripts/install-mingw.sh6
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md11
-rw-r--r--src/doc/rustc-dev-guide/src/implementing_new_features.md4
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/avr-none.md81
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md2
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md2
-rw-r--r--src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md5
-rw-r--r--src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md5
-rw-r--r--src/etc/rust_analyzer_zed.json52
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/librustdoc/clean/utils.rs71
-rw-r--r--src/librustdoc/doctest/make.rs16
-rw-r--r--src/librustdoc/html/render/print_item.rs28
-rw-r--r--src/librustdoc/html/render/sidebar.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs3
-rw-r--r--src/tools/compiletest/src/header/tests.rs3
-rw-r--r--src/tools/error_index_generator/Cargo.toml1
-rw-r--r--src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs6
-rw-r--r--src/tools/llvm-bitcode-linker/src/linker.rs13
-rw-r--r--src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr2
-rw-r--r--src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs30
-rw-r--r--src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr15
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs30
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs12
-rw-r--r--src/tools/rustbook/Cargo.lock11
-rw-r--r--src/tools/rustbook/Cargo.toml3
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/target_policy.rs1
-rw-r--r--tests/assembly/asm/avr-modifiers.rs2
-rw-r--r--tests/assembly/asm/avr-types.rs2
-rw-r--r--tests/assembly/closure-inherit-target-feature.rs7
-rw-r--r--tests/assembly/targets/targets-elf.rs6
-rw-r--r--tests/assembly/targets/targets-pe.rs6
-rw-r--r--tests/assembly/x86-return-float.rs42
-rw-r--r--tests/assembly/x86_64-windows-i128-abi.rs26
-rw-r--r--tests/codegen/abi-x86-sse.rs36
-rw-r--r--tests/codegen/asm/avr-clobbers.rs2
-rw-r--r--tests/codegen/avr/avr-func-addrspace.rs2
-rw-r--r--tests/codegen/float/f128.rs82
-rw-r--r--tests/codegen/float/f16.rs43
-rw-r--r--tests/codegen/i128-x86-callconv.rs38
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs2
-rw-r--r--tests/codegen/intrinsics/transmute-x64.rs9
-rw-r--r--tests/codegen/intrinsics/transmute.rs11
-rw-r--r--tests/codegen/issues/issue-32031.rs6
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs17
-rw-r--r--tests/codegen/simd/packed-simd.rs25
-rw-r--r--tests/codegen/simd/project-to-simd-array-field.rs31
-rw-r--r--tests/codegen/slice-iter-nonnull.rs6
-rw-r--r--tests/codegen/transmute-scalar.rs2
-rw-r--r--tests/codegen/unchecked_shifts.rs60
-rw-r--r--tests/codegen/uninhabited-transparent-return-abi.rs44
-rw-r--r--tests/codegen/union-abi.rs18
-rw-r--r--tests/coverage/holes.cov-map31
-rw-r--r--tests/coverage/holes.coverage41
-rw-r--r--tests/coverage/holes.rs33
-rw-r--r--tests/crashes/103899.rs27
-rw-r--r--tests/crashes/105299.rs19
-rw-r--r--tests/crashes/project-to-simd-array-field.rs33
-rw-r--r--tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff2
-rw-r--r--tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff2
-rw-r--r--tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff2
-rw-r--r--tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir248
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir186
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir192
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir124
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir124
-rw-r--r--tests/run-make/avr-rjmp-offset/rmake.rs8
-rw-r--r--tests/rustdoc-gui/sidebar-foreign-impl-sort.goml15
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs18
-rw-r--r--tests/ui/abi/c-zst.aarch64-darwin.stderr2
-rw-r--r--tests/ui/abi/c-zst.powerpc-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.s390x-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.sparc64-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.x86_64-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr2
-rw-r--r--tests/ui/abi/debug.stderr24
-rw-r--r--tests/ui/abi/sysv64-zst.stderr2
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr2
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr6
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr6
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr6
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr18
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr18
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/nested.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs1
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr2
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr2
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs1
-rw-r--r--tests/ui/dropck/dropck-only-error-ambiguity.rs23
-rw-r--r--tests/ui/dropck/dropck-only-error-ambiguity.stderr11
-rw-r--r--tests/ui/dropck/dropck-only-error-async.rs (renamed from tests/crashes/135039.rs)13
-rw-r--r--tests/ui/dropck/dropck-only-error-async.stderr15
-rw-r--r--tests/ui/dropck/dropck-only-error-gat.rs (renamed from tests/crashes/91985.rs)9
-rw-r--r--tests/ui/dropck/dropck-only-error-gat.stderr15
-rw-r--r--tests/ui/dropck/dropck-only-error.rs23
-rw-r--r--tests/ui/dropck/dropck-only-error.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs2
-rw-r--r--tests/ui/generic-associated-types/issue-91883.current.stderr (renamed from tests/ui/generic-associated-types/issue-91883.stderr)6
-rw-r--r--tests/ui/generic-associated-types/issue-91883.next.stderr20
-rw-r--r--tests/ui/generic-associated-types/issue-91883.rs4
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs3
-rw-r--r--tests/ui/implied-bounds/bevy_world_query.rs2
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr4
-rw-r--r--tests/ui/issues/issue-20831-debruijn.stderr4
-rw-r--r--tests/ui/layout/debug.rs5
-rw-r--r--tests/ui/layout/debug.stderr30
-rw-r--r--tests/ui/layout/hexagon-enum.stderr10
-rw-r--r--tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr17
-rw-r--r--tests/ui/layout/issue-96185-overaligned-enum.stderr6
-rw-r--r--tests/ui/layout/normalization-failure.rs57
-rw-r--r--tests/ui/layout/normalization-failure.stderr12
-rw-r--r--tests/ui/layout/thumb-enum.stderr10
-rw-r--r--tests/ui/layout/zero-sized-array-enum-niche.stderr13
-rw-r--r--tests/ui/lint/invalid_from_utf8.rs1
-rw-r--r--tests/ui/lint/invalid_from_utf8.stderr80
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.rs5
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.stderr36
-rw-r--r--tests/ui/nll/normalization-bounds-error.stderr4
-rw-r--r--tests/ui/parser/doc-before-bad-variant.rs6
-rw-r--r--tests/ui/parser/doc-before-bad-variant.stderr13
-rw-r--r--tests/ui/parser/doc-before-syntax-error.rs2
-rw-r--r--tests/ui/parser/doc-before-syntax-error.stderr8
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs7
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs48
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr37
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr22
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs24
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr12
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr25
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr4
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr103
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr97
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs122
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr61
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr55
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs16
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr219
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr20
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs121
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr52
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr310
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr50
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr9
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr20
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs26
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr9
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr46
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr51
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed20
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr12
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs20
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr10
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr43
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed20
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr10
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs17
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs37
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr133
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr122
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs87
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr82
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr122
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed11
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs11
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr38
-rw-r--r--tests/ui/process/process-sigpipe.rs17
-rw-r--r--tests/ui/regions/regions-normalize-in-where-clause-list.stderr4
-rw-r--r--tests/ui/regions/resolve-re-error-ice.stderr4
-rw-r--r--tests/ui/repr/16-bit-repr-c-enum.rs2
-rw-r--r--tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr50
-rw-r--r--tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr50
-rw-r--r--tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr50
-rw-r--r--tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr50
-rw-r--r--tests/ui/repr/repr-c-int-dead-variants.stderr50
-rw-r--r--tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs123
-rw-r--r--tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr251
-rw-r--r--tests/ui/resolve/enum-expected-value-suggest-variants.rs58
-rw-r--r--tests/ui/resolve/enum-expected-value-suggest-variants.stderr234
-rw-r--r--tests/ui/resolve/issue-22692.rs60
-rw-r--r--tests/ui/resolve/issue-22692.stderr119
-rw-r--r--tests/ui/sse-simd-abi-checks.rs (renamed from tests/ui/sse-abi-checks.rs)5
-rw-r--r--tests/ui/sse-simd-abi-checks.stderr (renamed from tests/ui/sse-abi-checks.stderr)4
-rw-r--r--tests/ui/static/static-lifetime.stderr4
-rw-r--r--tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs6
-rw-r--r--tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr23
-rw-r--r--tests/ui/traits/const-traits/predicate-entailment-passes.rs11
-rw-r--r--tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr4
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr12
-rw-r--r--tests/ui/traits/next-solver/gat-wf.rs16
-rw-r--r--tests/ui/traits/next-solver/gat-wf.stderr15
-rw-r--r--tests/ui/traits/question-mark-result-err-mismatch.rs1
-rw-r--r--tests/ui/traits/question-mark-result-err-mismatch.stderr6
-rw-r--r--tests/ui/try-block/try-block-bad-type.stderr1
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr1
-rw-r--r--tests/ui/try-trait/issue-32709.stderr1
-rw-r--r--tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr4
-rw-r--r--tests/ui/type/pattern_types/range_patterns.stderr9
-rw-r--r--tests/ui/typeck/issue-103899.current.stderr15
-rw-r--r--tests/ui/typeck/issue-103899.next.stderr15
-rw-r--r--tests/ui/typeck/issue-103899.rs5
-rw-r--r--tests/ui/uninhabited/uninhabited-transparent-return-abi.rs33
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.rs4
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.stderr12
415 files changed, 7475 insertions, 3633 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0934e42b277..de144ee6104 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -70,6 +70,7 @@ jobs:
       HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
       DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
       SCCACHE_BUCKET: rust-lang-ci-sccache2
+      SCCACHE_REGION: us-west-1
       CACHE_DOMAIN: ci-caches.rust-lang.org
     continue-on-error: ${{ matrix.continue_on_error || false }}
     strategy:
@@ -173,6 +174,11 @@ jobs:
       - name: ensure the stable version number is correct
         run: src/ci/scripts/verify-stable-version-number.sh
 
+      # Show the environment just before we run the build
+      # This makes it easier to diagnose problems with the above install scripts.
+      - name: show the current environment
+        run: src/ci/scripts/dump-environment.sh
+
       - name: run the build
         # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
         run: src/ci/scripts/run-build-from-ci.sh 2>&1
diff --git a/Cargo.lock b/Cargo.lock
index e9ee3c6b36e..c31fed86bc8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -62,19 +62,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
 [[package]]
-name = "ammonia"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
-dependencies = [
- "html5ever",
- "maplit",
- "once_cell",
- "tendril",
- "url",
-]
-
-[[package]]
 name = "android-tzdata"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -513,16 +500,6 @@ dependencies = [
  "anstyle",
  "clap_lex",
  "strsim",
- "terminal_size",
-]
-
-[[package]]
-name = "clap_complete"
-version = "4.5.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0"
-dependencies = [
- "clap",
 ]
 
 [[package]]
@@ -1085,18 +1062,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 
 [[package]]
-name = "elasticlunr-rs"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571"
-dependencies = [
- "regex",
- "serde",
- "serde_derive",
- "serde_json",
-]
-
-[[package]]
 name = "elsa"
 version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1160,13 +1125,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "error_index_generator"
-version = "0.0.0"
-dependencies = [
- "mdbook",
-]
-
-[[package]]
 name = "expect-test"
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1518,22 +1476,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "handlebars"
-version = "6.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6b224b95c1e668ac0270325ad563b2eef1469fbbb8959bc7c692c844b813d9"
-dependencies = [
- "derive_builder",
- "log",
- "num-order",
- "pest",
- "pest_derive",
- "serde",
- "serde_json",
- "thiserror 2.0.11",
-]
-
-[[package]]
 name = "hashbrown"
 version = "0.14.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2190,12 +2132,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
 [[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
-[[package]]
 name = "markup5ever"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2229,34 +2165,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "mdbook"
-version = "0.4.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148"
-dependencies = [
- "ammonia",
- "anyhow",
- "chrono",
- "clap",
- "clap_complete",
- "elasticlunr-rs",
- "env_logger",
- "handlebars",
- "log",
- "memchr",
- "once_cell",
- "opener",
- "pulldown-cmark 0.10.3",
- "regex",
- "serde",
- "serde_json",
- "shlex",
- "tempfile",
- "toml 0.5.11",
- "topological-sort",
-]
-
-[[package]]
 name = "measureme"
 version = "11.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2303,9 +2211,9 @@ dependencies = [
 
 [[package]]
 name = "minifier"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cf47565b1430f5fe6c81d3afcb4b835271348d7eb35294a4d592e38dd09ea22"
+checksum = "9bfdc64e2f805f3d12965f10522000bae36e88d2cfea44112331f467d4f4bf68"
 
 [[package]]
 name = "minimal-lexical"
@@ -2484,21 +2392,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "num-modular"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
-
-[[package]]
-name = "num-order"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
-dependencies = [
- "num-modular",
-]
-
-[[package]]
 name = "num-rational"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2719,51 +2612,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "pest"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
-dependencies = [
- "memchr",
- "thiserror 2.0.11",
- "ucd-trie",
-]
-
-[[package]]
-name = "pest_derive"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e"
-dependencies = [
- "pest",
- "pest_generator",
-]
-
-[[package]]
-name = "pest_generator"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b"
-dependencies = [
- "pest",
- "pest_meta",
- "proc-macro2",
- "quote",
- "syn 2.0.96",
-]
-
-[[package]]
-name = "pest_meta"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea"
-dependencies = [
- "once_cell",
- "pest",
- "sha2",
-]
-
-[[package]]
 name = "phf"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2923,36 +2771,18 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
-dependencies = [
- "bitflags",
- "memchr",
- "pulldown-cmark-escape 0.10.1",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
 dependencies = [
  "bitflags",
  "memchr",
- "pulldown-cmark-escape 0.11.0",
+ "pulldown-cmark-escape",
  "unicase",
 ]
 
 [[package]]
 name = "pulldown-cmark-escape"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
-
-[[package]]
-name = "pulldown-cmark-escape"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
@@ -3918,7 +3748,6 @@ dependencies = [
  "itertools",
  "rustc_abi",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3983,7 +3812,6 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -4174,7 +4002,6 @@ dependencies = [
  "rustc_apfloat",
  "rustc_arena",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_error_messages",
@@ -4304,7 +4131,6 @@ name = "rustc_next_trait_solver"
 version = "0.0.0"
 dependencies = [
  "derive-where",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_index",
  "rustc_macros",
@@ -4624,7 +4450,6 @@ dependencies = [
  "itertools",
  "rustc_abi",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -4663,7 +4488,6 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_abi",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_hir",
  "rustc_infer",
@@ -4679,7 +4503,6 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_abi",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -5311,16 +5134,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "terminal_size"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
-dependencies = [
- "rustix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
 name = "termize"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5561,12 +5374,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
 name = "tracing"
 version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5687,12 +5494,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "ucd-trie"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
-
-[[package]]
 name = "ui_test"
 version = "0.26.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 97e782d0df0..20a43aaaeeb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,6 @@ members = [
   "src/tools/clippy/clippy_dev",
   "src/tools/compiletest",
   "src/tools/run-make-support",
-  "src/tools/error_index_generator",
   "src/tools/linkchecker",
   "src/tools/lint-docs",
   "src/tools/miropt-test-tools",
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index 9fb70b80c9e..4529ab8058e 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         Ty: TyAbiInterface<'a, C> + Copy,
     {
         match self.backend_repr {
-            BackendRepr::Uninhabited => Err(Heterogeneous),
-
             // The primitive for this algorithm.
             BackendRepr::Scalar(scalar) => {
                 let kind = match scalar.primitive() {
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 45cd0b517f6..53243266f99 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -130,6 +130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             },
             backend_repr: BackendRepr::ScalarPair(a, b),
             largest_niche,
+            uninhabited: false,
             align,
             size,
             max_repr_align: None,
@@ -221,8 +222,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         LayoutData {
             variants: Variants::Empty,
             fields: FieldsShape::Primitive,
-            backend_repr: BackendRepr::Uninhabited,
+            backend_repr: BackendRepr::Memory { sized: true },
             largest_niche: None,
+            uninhabited: true,
             align: dl.i8_align,
             size: Size::ZERO,
             max_repr_align: None,
@@ -400,6 +402,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             fields: FieldsShape::Union(union_field_count),
             backend_repr: abi,
             largest_niche: None,
+            uninhabited: false,
             align,
             size: size.align_to(align.abi),
             max_repr_align,
@@ -447,7 +450,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 Scalar::Union { .. } => {}
             };
             match &mut st.backend_repr {
-                BackendRepr::Uninhabited => {}
                 BackendRepr::Scalar(scalar) => hide_niches(scalar),
                 BackendRepr::ScalarPair(a, b) => {
                     hide_niches(a);
@@ -639,9 +641,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             let same_size = size == variant_layouts[largest_variant_index].size;
             let same_align = align == variant_layouts[largest_variant_index].align;
 
-            let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) {
-                BackendRepr::Uninhabited
-            } else if same_size && same_align && others_zst {
+            let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
+            let abi = if same_size && same_align && others_zst {
                 match variant_layouts[largest_variant_index].backend_repr {
                     // When the total alignment and size match, we can use the
                     // same ABI as the scalar variant with the reserved niche.
@@ -683,6 +684,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 },
                 backend_repr: abi,
                 largest_niche,
+                uninhabited,
                 size,
                 align,
                 max_repr_align,
@@ -853,9 +855,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
         let mut abi = BackendRepr::Memory { sized: true };
 
-        if layout_variants.iter().all(|v| v.is_uninhabited()) {
-            abi = BackendRepr::Uninhabited;
-        } else if tag.size(dl) == size {
+        let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited());
+        if tag.size(dl) == size {
             // Make sure we only use scalar layout when the enum is entirely its
             // own tag (i.e. it has no padding nor any non-ZST variant fields).
             abi = BackendRepr::Scalar(tag);
@@ -995,6 +996,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 memory_index: [0].into(),
             },
             largest_niche,
+            uninhabited,
             backend_repr: abi,
             align,
             size,
@@ -1355,9 +1357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 _ => {}
             }
         }
-        if fields.iter().any(|f| f.is_uninhabited()) {
-            abi = BackendRepr::Uninhabited;
-        }
+        let uninhabited = fields.iter().any(|f| f.is_uninhabited());
 
         let unadjusted_abi_align = if repr.transparent() {
             match layout_of_single_non_zst_field {
@@ -1378,6 +1378,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             fields: FieldsShape::Arbitrary { offsets, memory_index },
             backend_repr: abi,
             largest_niche,
+            uninhabited,
             align,
             size,
             max_repr_align,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index dbb4bed5cdd..098638b6bcf 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1404,7 +1404,6 @@ impl AddressSpace {
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
 pub enum BackendRepr {
-    Uninhabited,
     Scalar(Scalar),
     ScalarPair(Scalar, Scalar),
     Vector {
@@ -1423,10 +1422,9 @@ impl BackendRepr {
     #[inline]
     pub fn is_unsized(&self) -> bool {
         match *self {
-            BackendRepr::Uninhabited
-            | BackendRepr::Scalar(_)
-            | BackendRepr::ScalarPair(..)
-            | BackendRepr::Vector { .. } => false,
+            BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
+                false
+            }
             BackendRepr::Memory { sized } => !sized,
         }
     }
@@ -1445,12 +1443,6 @@ impl BackendRepr {
         }
     }
 
-    /// Returns `true` if this is an uninhabited type
-    #[inline]
-    pub fn is_uninhabited(&self) -> bool {
-        matches!(*self, BackendRepr::Uninhabited)
-    }
-
     /// Returns `true` if this is a scalar type
     #[inline]
     pub fn is_scalar(&self) -> bool {
@@ -1471,7 +1463,7 @@ impl BackendRepr {
             BackendRepr::Vector { element, count } => {
                 cx.data_layout().vector_align(element.size(cx) * count)
             }
-            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
+            BackendRepr::Memory { .. } => return None,
         })
     }
 
@@ -1492,7 +1484,7 @@ impl BackendRepr {
                 // to make the size a multiple of align (e.g. for vectors of size 3).
                 (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
             }
-            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
+            BackendRepr::Memory { .. } => return None,
         })
     }
 
@@ -1506,9 +1498,7 @@ impl BackendRepr {
             BackendRepr::Vector { element, count } => {
                 BackendRepr::Vector { element: element.to_union(), count }
             }
-            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
-                BackendRepr::Memory { sized: true }
-            }
+            BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
         }
     }
 
@@ -1704,6 +1694,11 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
     /// The leaf scalar with the largest number of invalid values
     /// (i.e. outside of its `valid_range`), if it exists.
     pub largest_niche: Option<Niche>,
+    /// Is this type known to be uninhabted?
+    ///
+    /// This is separate from BackendRepr because uninhabited return types can affect ABI,
+    /// especially in the case of by-pointer struct returns, which allocate stack even when unused.
+    pub uninhabited: bool,
 
     pub align: AbiAndPrefAlign,
     pub size: Size,
@@ -1735,14 +1730,14 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
     /// Returns `true` if this is an aggregate type (including a ScalarPair!)
     pub fn is_aggregate(&self) -> bool {
         match self.backend_repr {
-            BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
+            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
             BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
         }
     }
 
     /// Returns `true` if this is an uninhabited type
     pub fn is_uninhabited(&self) -> bool {
-        self.backend_repr.is_uninhabited()
+        self.uninhabited
     }
 
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
@@ -1778,6 +1773,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
             fields: FieldsShape::Primitive,
             backend_repr: BackendRepr::Scalar(scalar),
             largest_niche,
+            uninhabited: false,
             size,
             align,
             max_repr_align: None,
@@ -1802,6 +1798,7 @@ where
             backend_repr,
             fields,
             largest_niche,
+            uninhabited,
             variants,
             max_repr_align,
             unadjusted_abi_align,
@@ -1813,6 +1810,7 @@ where
             .field("abi", backend_repr)
             .field("fields", fields)
             .field("largest_niche", largest_niche)
+            .field("uninhabited", uninhabited)
             .field("variants", variants)
             .field("max_repr_align", max_repr_align)
             .field("unadjusted_abi_align", unadjusted_abi_align)
@@ -1877,7 +1875,6 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
             BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
                 false
             }
-            BackendRepr::Uninhabited => self.size.bytes() == 0,
             BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
         }
     }
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index ff9d940ce9f..9884e191ea7 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -1,3 +1,10 @@
+//! Common utilities shared by both `rustc_ast` and `rustc_type_ir`.
+//!
+//! Don't depend on this crate directly; both of those crates should re-export
+//! the functionality. Additionally, if you're in scope of `rustc_middle`, then
+//! prefer imports via that too, to avoid needing to directly depend on (e.g.)
+//! `rustc_type_ir` for a single import.
+
 // tidy-alphabetical-start
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 #![cfg_attr(feature = "nightly", feature(never_type))]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index e778340cb65..b2cc58fbe11 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -18,12 +18,11 @@ use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter::OnlyBodies;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
     FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
-    Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
-    TerminatorKind, VarBindingForm, VarDebugInfoContents,
+    Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, StatementKind,
+    Terminator, TerminatorKind, VarBindingForm, VarDebugInfoContents,
 };
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 26a090f5579..96f48840468 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,7 +1,7 @@
 use std::collections::VecDeque;
 
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 
@@ -45,7 +45,22 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
 
             let block_data = &self.body[p.block];
 
-            match self.def_use(p, block_data.visitable(p.statement_index)) {
+            let mut visitor = DefUseVisitor {
+                body: self.body,
+                tcx: self.tcx,
+                region_vid: self.region_vid,
+                def_use_result: None,
+            };
+
+            let is_statement = p.statement_index < block_data.statements.len();
+
+            if is_statement {
+                visitor.visit_statement(&block_data.statements[p.statement_index], p);
+            } else {
+                visitor.visit_terminator(block_data.terminator.as_ref().unwrap(), p);
+            }
+
+            match visitor.def_use_result {
                 Some(DefUseResult::Def) => {}
 
                 Some(DefUseResult::UseLive { local }) => {
@@ -57,7 +72,7 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
                 }
 
                 None => {
-                    if p.statement_index < block_data.statements.len() {
+                    if is_statement {
                         queue.push_back(p.successor_within_block());
                     } else {
                         queue.extend(
@@ -77,19 +92,6 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
 
         None
     }
-
-    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
-        let mut visitor = DefUseVisitor {
-            body: self.body,
-            tcx: self.tcx,
-            region_vid: self.region_vid,
-            def_use_result: None,
-        };
-
-        thing.apply(location, &mut visitor);
-
-        visitor.def_use_result
-    }
 }
 
 struct DefUseVisitor<'a, 'tcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 07ea369c5c7..7da089c5e8c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -13,10 +13,9 @@ use rustc_infer::infer::{
 };
 use rustc_infer::traits::SelectionError;
 use rustc_middle::bug;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
-    LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
+    LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement,
     StatementKind, Terminator, TerminatorKind, find_self_call,
 };
 use rustc_middle::ty::print::Print;
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 22ce0fd1ea7..a98984a4b4c 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -33,7 +33,6 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_infer::infer::{
     InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
 };
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::fold::fold_regions;
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d2268c4779d..e0e3e028c61 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1267,6 +1267,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let sub_region_scc = self.constraint_sccs.scc(sub_region);
         let sup_region_scc = self.constraint_sccs.scc(sup_region);
 
+        if sub_region_scc == sup_region_scc {
+            debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC");
+            return true;
+        }
+
         // If we are checking that `'sup: 'sub`, and `'sub` contains
         // some placeholder that `'sup` cannot name, then this is only
         // true if `'sup` outlives static.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 62d49a62744..148e75aa84c 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,7 +3,8 @@ use rustc_index::bit_set::DenseBitSet;
 use rustc_index::interval::IntervalSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::for_liveness;
-use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
+use rustc_middle::span_bug;
 use rustc_middle::traits::query::DropckOutlivesResult;
 use rustc_middle::ty::relate::Relate;
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
@@ -11,7 +12,10 @@ use rustc_mir_dataflow::ResultsCursor;
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
-use rustc_span::DUMMY_SP;
+use rustc_span::{DUMMY_SP, Span};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
+use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::query::dropck_outlives;
 use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
 use tracing::debug;
 
@@ -162,9 +166,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
         for local in boring_locals {
             let local_ty = self.cx.body.local_decls[local].ty;
+            let local_span = self.cx.body.local_decls[local].source_info.span;
             let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
                 let typeck = &self.cx.typeck;
-                move || LivenessContext::compute_drop_data(typeck, local_ty)
+                move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
             });
 
             drop_data.dropck_result.report_overflows(
@@ -522,9 +527,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             values::pretty_print_points(self.location_map, live_at.iter()),
         );
 
+        let local_span = self.body.local_decls()[dropped_local].source_info.span;
         let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
             let typeck = &self.typeck;
-            move || Self::compute_drop_data(typeck, dropped_ty)
+            move || Self::compute_drop_data(typeck, dropped_ty, local_span)
         });
 
         if let Some(data) = &drop_data.region_constraint_data {
@@ -589,19 +595,44 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         }
     }
 
-    fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
-        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
+    fn compute_drop_data(
+        typeck: &TypeChecker<'_, 'tcx>,
+        dropped_ty: Ty<'tcx>,
+        span: Span,
+    ) -> DropData<'tcx> {
+        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty);
+
+        let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
 
-        match typeck
-            .infcx
-            .param_env
-            .and(DropckOutlives { dropped_ty })
-            .fully_perform(typeck.infcx, DUMMY_SP)
-        {
+        match op.fully_perform(typeck.infcx, DUMMY_SP) {
             Ok(TypeOpOutput { output, constraints, .. }) => {
                 DropData { dropck_result: output, region_constraint_data: constraints }
             }
-            Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+            Err(_) => {
+                // We don't run dropck on HIR, and dropck looks inside fields of
+                // types, so there's no guarantee that it succeeds. We also
+                // can't rely on the the `ErrorGuaranteed` from `fully_perform` here
+                // because it comes from delay_span_bug.
+                let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
+                let errors =
+                    match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) {
+                        Ok(_) => ocx.select_all_or_error(),
+                        Err(e) => {
+                            if e.is_empty() {
+                                ocx.select_all_or_error()
+                            } else {
+                                e
+                            }
+                        }
+                    };
+
+                if !errors.is_empty() {
+                    typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
+                } else {
+                    span_bug!(span, "Rerunning drop data query produced no error.");
+                }
+                DropData { dropck_result: Default::default(), region_constraint_data: None }
+            }
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 93081919ec7..bd0d98028ae 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -19,7 +19,6 @@ use rustc_infer::infer::{
     BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
 };
 use rustc_infer::traits::PredicateObligations;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::traits::query::NoSolution;
@@ -457,38 +456,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
     fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
         self.super_local_decl(local, local_decl);
 
-        if let Some(user_ty) = &local_decl.user_ty {
-            for (user_ty, span) in user_ty.projections_and_spans() {
-                let ty = if !local_decl.is_nonref_binding() {
-                    // If we have a binding of the form `let ref x: T = ..`
-                    // then remove the outermost reference so we can check the
-                    // type annotation for the remaining type.
-                    if let ty::Ref(_, rty, _) = local_decl.ty.kind() {
-                        *rty
-                    } else {
-                        bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
-                    }
-                } else {
-                    local_decl.ty
-                };
+        for user_ty in
+            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
+        {
+            let span = self.typeck.user_type_annotations[user_ty.base].span;
+
+            let ty = if local_decl.is_nonref_binding() {
+                local_decl.ty
+            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
+                // If we have a binding of the form `let ref x: T = ..`
+                // then remove the outermost reference so we can check the
+                // type annotation for the remaining type.
+                rty
+            } else {
+                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
+            };
 
-                if let Err(terr) = self.typeck.relate_type_and_user_type(
-                    ty,
-                    ty::Invariant,
-                    user_ty,
-                    Locations::All(*span),
-                    ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
-                ) {
-                    span_mirbug!(
-                        self,
-                        local,
-                        "bad user type on variable {:?}: {:?} != {:?} ({:?})",
-                        local,
-                        local_decl.ty,
-                        local_decl.user_ty,
-                        terr,
-                    );
-                }
+            if let Err(terr) = self.typeck.relate_type_and_user_type(
+                ty,
+                ty::Invariant,
+                user_ty,
+                Locations::All(span),
+                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
+            ) {
+                span_mirbug!(
+                    self,
+                    local,
+                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
+                    local,
+                    local_decl.ty,
+                    local_decl.user_ty,
+                    terr,
+                );
             }
         }
     }
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 4e6f82ac849..9a68eeb3326 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -21,6 +21,7 @@ use std::iter;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Diag;
 use rustc_hir::BodyOwnerKind;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::IndexVec;
@@ -603,7 +604,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
             BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
                 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
-                if self.mir_def.to_def_id() == typeck_root_def_id {
+                if self.mir_def.to_def_id() == typeck_root_def_id
+                    // Do not ICE when checking default_field_values consts with lifetimes (#135649)
+                    && DefKind::Field != tcx.def_kind(tcx.parent(typeck_root_def_id))
+                {
                     let args =
                         self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
                     DefiningTy::Const(self.mir_def.to_def_id(), args)
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 521a250ab82..c74efeb59f3 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -65,7 +65,7 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
     if fx.clif_comments.enabled() {
         fx.add_global_comment(String::new());
         fx.add_global_comment(
-            "kind  local ty                              size align (abi,pref)".to_string(),
+            "kind  local ty                              size align (abi)".to_string(),
         );
     }
 }
@@ -84,14 +84,13 @@ pub(super) fn add_local_place_comments<'tcx>(
     let (kind, extra) = place.debug_comment();
 
     fx.add_global_comment(format!(
-        "{:<5} {:5} {:30} {:4}b {}, {}{}{}",
+        "{:<5} {:5} {:30} {:4}b {}{}{}",
         kind,
         format!("{:?}", local),
         format!("{:?}", ty),
         size.bytes(),
         align.abi.bytes(),
-        align.pref.bytes(),
-        if extra.is_empty() { "" } else { "              " },
+        if extra.is_empty() { "" } else { "                " },
         extra,
     ));
 }
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 425b2adf32a..bcc70f4567f 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -272,7 +272,7 @@ fn data_id_for_static(
             .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
             .unwrap()
             .align
-            .pref
+            .abi
             .bytes();
 
         let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index a9b8e1bd393..1b3f86c8405 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> {
             }
             CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self),
             CPlaceInner::Addr(to_ptr, None) => {
-                if dst_layout.size == Size::ZERO
-                    || dst_layout.backend_repr == BackendRepr::Uninhabited
-                {
+                if dst_layout.size == Size::ZERO {
                     return;
                 }
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index b8e37b60480..c8b7616e645 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -989,10 +989,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             OperandValue::Ref(place.val)
         } else if place.layout.is_gcc_immediate() {
             let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
-            if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
-                scalar_load_metadata(self, load, scalar);
-            }
-            OperandValue::Immediate(self.to_immediate(load, place.layout))
+            OperandValue::Immediate(
+                if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
+                    scalar_load_metadata(self, load, scalar);
+                    self.to_immediate_scalar(load, *scalar)
+                } else {
+                    load
+                },
+            )
         } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
             let b_offset = a.size(self).align_to(b.align(self).abi);
 
@@ -1694,7 +1698,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
         if scalar.is_bool() {
-            return self.trunc(val, self.cx().type_i1());
+            return self.unchecked_utrunc(val, self.cx().type_i1());
         }
         val
     }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index a1123fafe2f..433868e238a 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -9,7 +9,7 @@ use gccjit::FunctionType;
 use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
 #[cfg(feature = "master")]
 use rustc_abi::ExternAbi;
-use rustc_abi::HasDataLayout;
+use rustc_abi::{BackendRepr, HasDataLayout};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::IntPredicate;
@@ -181,14 +181,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             sym::volatile_load | sym::unaligned_volatile_load => {
                 let tp_ty = fn_args.type_at(0);
                 let ptr = args[0].immediate();
+                let layout = self.layout_of(tp_ty);
                 let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
                     let gcc_ty = ty.gcc_type(self);
                     self.volatile_load(gcc_ty, ptr)
                 } else {
-                    self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
+                    self.volatile_load(layout.gcc_type(self), ptr)
                 };
                 // TODO(antoyo): set alignment.
-                self.to_immediate(load, self.layout_of(tp_ty))
+                if let BackendRepr::Scalar(scalar) = layout.backend_repr {
+                    self.to_immediate_scalar(load, scalar)
+                } else {
+                    load
+                }
             }
             sym::volatile_store => {
                 let dst = args[0].deref(self.cx());
@@ -310,7 +315,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                 let layout = self.layout_of(tp_ty).layout;
                 let _use_integer_compare = match layout.backend_repr() {
                     Scalar(_) | ScalarPair(_, _) => true,
-                    Uninhabited | Vector { .. } => false,
+                    Vector { .. } => false,
                     Memory { .. } => {
                         // For rusty ABIs, small aggregates are actually passed
                         // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 8b8b54753e7..bac4fc51300 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
                 false,
             );
         }
-        BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
+        BackendRepr::Memory { .. } => {}
     }
 
     let name = match *layout.ty.kind() {
@@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     fn is_gcc_immediate(&self) -> bool {
         match self.backend_repr {
             BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
-            BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
-                false
-            }
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
         }
     }
 
     fn is_gcc_scalar_pair(&self) -> bool {
         match self.backend_repr {
             BackendRepr::ScalarPair(..) => true,
-            BackendRepr::Uninhabited
-            | BackendRepr::Scalar(_)
-            | BackendRepr::Vector { .. }
-            | BackendRepr::Memory { .. } => false,
+            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
+                false
+            }
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 28f423efc21..8c75125e009 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -2,19 +2,18 @@ use std::borrow::Borrow;
 use std::cmp;
 
 use libc::c_uint;
-use rustc_abi as abi;
-pub(crate) use rustc_abi::ExternAbi;
-use rustc_abi::{HasDataLayout, Primitive, Reg, RegKind, Size};
+use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::LayoutOf;
-pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA};
 use rustc_middle::{bug, ty};
 use rustc_session::config;
-pub(crate) use rustc_target::callconv::*;
+use rustc_target::callconv::{
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode,
+};
 use rustc_target::spec::SanitizerSet;
 use smallvec::SmallVec;
 
@@ -458,7 +457,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         match &self.ret.mode {
             PassMode::Direct(attrs) => {
                 attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
-                if let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
+                if let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
                     apply_range_attr(llvm::AttributePlace::ReturnValue, scalar);
                 }
             }
@@ -499,7 +498,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 }
                 PassMode::Direct(attrs) => {
                     let i = apply(attrs);
-                    if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
+                    if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
                         apply_range_attr(llvm::AttributePlace::Argument(i), scalar);
                     }
                 }
@@ -514,9 +513,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 PassMode::Pair(a, b) => {
                     let i = apply(a);
                     let ii = apply(b);
-                    if let abi::BackendRepr::ScalarPair(scalar_a, scalar_b) =
-                        arg.layout.backend_repr
-                    {
+                    if let BackendRepr::ScalarPair(scalar_a, scalar_b) = arg.layout.backend_repr {
                         apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a);
                         apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
                     }
@@ -576,7 +573,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         }
         if bx.cx.sess().opts.optimize != config::OptLevel::No
                 && llvm_util::get_version() < (19, 0, 0)
-                && let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
+                && let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
                 && matches!(scalar.primitive(), Primitive::Int(..))
                 // If the value is a boolean, the range is 0..2 and that ultimately
                 // become 0..0 when the type becomes i1, which would be rejected
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index e10a4d63407..e1609e31c07 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -29,13 +29,13 @@ use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
 use crate::abi::FnAbiLlvmExt;
-use crate::attributes;
 use crate::common::Funclet;
 use crate::context::{CodegenCx, SimpleCx};
 use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, Metadata, True};
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
+use crate::{attributes, llvm_util};
 
 #[must_use]
 pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SimpleCx<'ll>>> {
@@ -606,7 +606,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
         if scalar.is_bool() {
-            return self.trunc(val, self.cx().type_i1());
+            return self.unchecked_utrunc(val, self.cx().type_i1());
         }
         val
     }
@@ -746,10 +746,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 let load = self.load(llty, place.val.llval, place.val.align);
                 if let abi::BackendRepr::Scalar(scalar) = place.layout.backend_repr {
                     scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
+                    self.to_immediate_scalar(load, scalar)
+                } else {
+                    load
                 }
-                load
             });
-            OperandValue::Immediate(self.to_immediate(llval, place.layout))
+            OperandValue::Immediate(llval)
         } else if let abi::BackendRepr::ScalarPair(a, b) = place.layout.backend_repr {
             let b_offset = a.size(self).align_to(b.align(self).abi);
 
@@ -942,6 +944,34 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) }
     }
 
+    fn unchecked_utrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
+        debug_assert_ne!(self.val_ty(val), dest_ty);
+
+        let trunc = self.trunc(val, dest_ty);
+        if llvm_util::get_version() >= (19, 0, 0) {
+            unsafe {
+                if llvm::LLVMIsAInstruction(trunc).is_some() {
+                    llvm::LLVMSetNUW(trunc, True);
+                }
+            }
+        }
+        trunc
+    }
+
+    fn unchecked_strunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
+        debug_assert_ne!(self.val_ty(val), dest_ty);
+
+        let trunc = self.trunc(val, dest_ty);
+        if llvm_util::get_version() >= (19, 0, 0) {
+            unsafe {
+                if llvm::LLVMIsAInstruction(trunc).is_some() {
+                    llvm::LLVMSetNSW(trunc, True);
+                }
+            }
+        }
+        trunc
+    }
+
     fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) }
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 59c3fe635d0..98d59f5a8ae 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -11,7 +11,9 @@ use rustc_codegen_ssa::traits::*;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{
+    HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
+};
 use rustc_middle::ty::{
     self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
 };
@@ -34,12 +36,12 @@ use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::dwarf_const;
 use crate::debuginfo::metadata::type_map::build_type_with_children;
 use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
+use crate::llvm;
 use crate::llvm::debuginfo::{
     DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
     DebugNameTableKind,
 };
 use crate::value::Value;
-use crate::{abi, llvm};
 
 impl PartialEq for llvm::Metadata {
     fn eq(&self, other: &Self) -> bool {
@@ -211,16 +213,16 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                     };
 
                     let layout = cx.layout_of(layout_type);
-                    let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
-                    let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
+                    let addr_field = layout.field(cx, WIDE_PTR_ADDR);
+                    let extra_field = layout.field(cx, WIDE_PTR_EXTRA);
 
                     let (addr_field_name, extra_field_name) = match wide_pointer_kind {
                         WidePtrKind::Dyn => ("pointer", "vtable"),
                         WidePtrKind::Slice => ("data_ptr", "length"),
                     };
 
-                    assert_eq!(abi::WIDE_PTR_ADDR, 0);
-                    assert_eq!(abi::WIDE_PTR_EXTRA, 1);
+                    assert_eq!(WIDE_PTR_ADDR, 0);
+                    assert_eq!(WIDE_PTR_EXTRA, 1);
 
                     // The data pointer type is a regular, thin pointer, regardless of whether this
                     // is a slice or a trait object.
@@ -242,7 +244,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                             owner,
                             addr_field_name,
                             (addr_field.size, addr_field.align.abi),
-                            layout.fields.offset(abi::WIDE_PTR_ADDR),
+                            layout.fields.offset(WIDE_PTR_ADDR),
                             DIFlags::FlagZero,
                             data_ptr_type_di_node,
                             None,
@@ -252,7 +254,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                             owner,
                             extra_field_name,
                             (extra_field.size, extra_field.align.abi),
-                            layout.fields.offset(abi::WIDE_PTR_EXTRA),
+                            layout.fields.offset(WIDE_PTR_EXTRA),
                             DIFlags::FlagZero,
                             type_di_node(cx, extra_field.ty),
                             None,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 17f2d5f4e73..10819a53b1d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -22,6 +22,7 @@ use rustc_session::config::{self, DebugInfo};
 use rustc_span::{
     BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId, Symbol,
 };
+use rustc_target::callconv::FnAbi;
 use rustc_target::spec::DebuginfoKind;
 use smallvec::SmallVec;
 use tracing::debug;
@@ -29,7 +30,6 @@ use tracing::debug;
 use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node};
 use self::namespace::mangled_name_of_instance;
 use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
-use crate::abi::FnAbi;
 use crate::builder::Builder;
 use crate::common::{AsCCharPtr, CodegenCx};
 use crate::llvm;
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index cebceef1b93..e79662ebc64 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -16,10 +16,11 @@ use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_middle::ty::{Instance, Ty};
 use rustc_sanitizers::{cfi, kcfi};
+use rustc_target::callconv::FnAbi;
 use smallvec::SmallVec;
 use tracing::debug;
 
-use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::abi::FnAbiLlvmExt;
 use crate::common::AsCCharPtr;
 use crate::context::{CodegenCx, SimpleCx};
 use crate::llvm::AttributePlace::Function;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 8b976885904..f68365f6c69 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1,7 +1,7 @@
 use std::assert_matches::assert_matches;
 use std::cmp::Ordering;
 
-use rustc_abi::{self as abi, Align, Float, HasDataLayout, Primitive, Size};
+use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size};
 use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
@@ -14,10 +14,11 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
+use rustc_target::callconv::{FnAbi, PassMode};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 use tracing::debug;
 
-use crate::abi::{ExternAbi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode};
+use crate::abi::{FnAbiLlvmExt, LlvmType};
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 use crate::llvm::{self, Metadata};
@@ -257,7 +258,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
             sym::va_arg => {
                 match fn_abi.ret.layout.backend_repr {
-                    abi::BackendRepr::Scalar(scalar) => {
+                    BackendRepr::Scalar(scalar) => {
                         match scalar.primitive() {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
@@ -470,12 +471,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             sym::raw_eq => {
-                use abi::BackendRepr::*;
+                use BackendRepr::*;
                 let tp_ty = fn_args.type_at(0);
                 let layout = self.layout_of(tp_ty).layout;
                 let use_integer_compare = match layout.backend_repr() {
                     Scalar(_) | ScalarPair(_, _) => true,
-                    Uninhabited | Vector { .. } => false,
+                    Vector { .. } => false,
                     Memory { .. } => {
                         // For rusty ABIs, small aggregates are actually passed
                         // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
@@ -582,8 +583,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 }
 
                 let llret_ty = if ret_ty.is_simd()
-                    && let abi::BackendRepr::Memory { .. } =
-                        self.layout_of(ret_ty).layout.backend_repr
+                    && let BackendRepr::Memory { .. } = self.layout_of(ret_ty).layout.backend_repr
                 {
                     let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
                     let elem_ll_ty = match elem_ty.kind() {
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index b0b6da869da..ba01fbff385 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
             let element = layout.scalar_llvm_type_at(cx, element);
             return cx.type_vector(element, count);
         }
-        BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
+        BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
     }
 
     let name = match layout.ty.kind() {
@@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     fn is_llvm_immediate(&self) -> bool {
         match self.backend_repr {
             BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
-            BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
-                false
-            }
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
         }
     }
 
     fn is_llvm_scalar_pair(&self) -> bool {
         match self.backend_repr {
             BackendRepr::ScalarPair(..) => true,
-            BackendRepr::Uninhabited
-            | BackendRepr::Scalar(_)
-            | BackendRepr::Vector { .. }
-            | BackendRepr::Memory { .. } => false,
+            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
+                false
+            }
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 105a4cb81f0..a8d917f0fdb 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1990,6 +1990,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor)
     if let Some(args) = sess.target.pre_link_args.get(&flavor) {
         cmd.verbatim_args(args.iter().map(Deref::deref));
     }
+
     cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
 }
 
@@ -2518,6 +2519,12 @@ fn add_order_independent_options(
             "--target-cpu",
             &codegen_results.crate_info.target_cpu,
         ]);
+        if codegen_results.crate_info.target_features.len() > 0 {
+            cmd.link_arg(&format!(
+                "--target-feature={}",
+                &codegen_results.crate_info.target_features.join(",")
+            ));
+        }
     } else if flavor == LinkerFlavor::Ptx {
         cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]);
     } else if flavor == LinkerFlavor::Bpf {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e3ace01c1eb..8900405c1b8 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -153,6 +153,7 @@ pub(crate) fn get_linker<'a>(
             hinted_static: None,
             is_ld: cc == Cc::No,
             is_gnu: flavor.is_gnu(),
+            uses_lld: flavor.uses_lld(),
         }) as Box<dyn Linker>,
         LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
@@ -361,6 +362,7 @@ struct GccLinker<'a> {
     // Link as ld
     is_ld: bool,
     is_gnu: bool,
+    uses_lld: bool,
 }
 
 impl<'a> GccLinker<'a> {
@@ -552,6 +554,7 @@ impl<'a> Linker for GccLinker<'a> {
                 self.link_args(&["--entry", "_initialize"]);
             }
         }
+
         // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
         // it switches linking for libc and similar system libraries to static without using
         // any `#[link]` attributes in the `libc` crate, see #72782 for details.
@@ -567,6 +570,15 @@ impl<'a> Linker for GccLinker<'a> {
         {
             self.cc_arg("--static-crt");
         }
+
+        // avr-none doesn't have default ISA, users must specify which specific
+        // CPU (well, microcontroller) they are targetting using `-Ctarget-cpu`.
+        //
+        // Currently this makes sense only when using avr-gcc as a linker, since
+        // it brings a couple of hand-written important intrinsics from libgcc.
+        if self.sess.target.arch == "avr" && !self.uses_lld {
+            self.verbatim_arg(format!("-mmcu={}", self.target_cpu));
+        }
     }
 
     fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index e800492dad0..40238f4b491 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -24,7 +24,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::Session;
-use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
+use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
 use rustc_span::{DUMMY_SP, Symbol, sym};
 use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
@@ -364,13 +364,7 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let rhs_sz = bx.cx().int_width(rhs_llty);
     let lhs_sz = bx.cx().int_width(lhs_llty);
     if lhs_sz < rhs_sz {
-        if is_unchecked && bx.sess().opts.optimize != OptLevel::No {
-            // FIXME: Use `trunc nuw` once that's available
-            let inrange = bx.icmp(IntPredicate::IntULE, rhs, mask);
-            bx.assume(inrange);
-        }
-
-        bx.trunc(rhs, lhs_llty)
+        if is_unchecked { bx.unchecked_utrunc(rhs, lhs_llty) } else { bx.trunc(rhs, lhs_llty) }
     } else if lhs_sz > rhs_sz {
         // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the
         // RHS to `255i32`. But then we mask the shift amount to be within the size of the LHS
@@ -921,6 +915,7 @@ impl CrateInfo {
         let n_crates = crates.len();
         let mut info = CrateInfo {
             target_cpu,
+            target_features: tcx.global_backend_features(()).clone(),
             crate_types,
             exported_symbols,
             linked_symbols,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 428a45975f1..9d2ac219d59 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -190,6 +190,7 @@ impl From<&cstore::NativeLib> for NativeLib {
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
     pub target_cpu: String,
+    pub target_features: Vec<String>,
     pub crate_types: Vec<CrateType>,
     pub exported_symbols: UnordMap<CrateType, Vec<String>>,
     pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>,
@@ -230,6 +231,7 @@ pub fn provide(providers: &mut Providers) {
     crate::base::provide(providers);
     crate::target_features::provide(providers);
     crate::codegen_attrs::provide(providers);
+    providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![];
 }
 
 /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc`
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 616d748a299..49074996174 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange};
 use rustc_ast as ast;
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::mir::{
-    self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason,
-};
+use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty};
@@ -942,7 +940,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     &fn_abi.ret,
                     &mut llargs,
                     Some(intrinsic),
-                    target,
                 );
                 let dest = match ret_dest {
                     _ if fn_abi.ret.is_indirect() => llargs[0],
@@ -998,19 +995,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         };
 
         let mut llargs = Vec::with_capacity(arg_count);
-        let destination = target.as_ref().map(|&target| {
-            (
-                self.make_return_dest(
-                    bx,
-                    destination,
-                    &fn_abi.ret,
-                    &mut llargs,
-                    None,
-                    Some(target),
-                ),
-                target,
-            )
-        });
+
+        // We still need to call `make_return_dest` even if there's no `target`, since
+        // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
+        // and `make_return_dest` adds the return-place indirect pointer to `llargs`.
+        let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
+        let destination = target.map(|target| (return_dest, target));
 
         // Split the rust-call tupled arguments off.
         let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() {
@@ -1040,7 +1030,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             let (idx, _) = op.layout.non_1zst_field(bx).expect(
                                 "not exactly one non-1-ZST field in a `DispatchFromDyn` type",
                             );
-                            op = op.extract_field(bx, idx);
+                            op = op.extract_field(self, bx, idx);
                         }
 
                         // Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
@@ -1072,7 +1062,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             let (idx, _) = op.layout.non_1zst_field(bx).expect(
                                 "not exactly one non-1-ZST field in a `DispatchFromDyn` type",
                             );
-                            op = op.extract_field(bx, idx);
+                            op = op.extract_field(self, bx, idx);
                         }
 
                         // Make sure that we've actually unwrapped the rcvr down
@@ -1572,9 +1562,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     if scalar.is_bool() {
                         bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
                     }
+                    // We store bools as `i8` so we need to truncate to `i1`.
+                    llval = bx.to_immediate_scalar(llval, scalar);
                 }
-                // We store bools as `i8` so we need to truncate to `i1`.
-                llval = bx.to_immediate(llval, arg.layout);
             }
         }
 
@@ -1604,7 +1594,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         } else {
             // If the tuple is immediate, the elements are as well.
             for i in 0..tuple.layout.fields.count() {
-                let op = tuple.extract_field(bx, i);
+                let op = tuple.extract_field(self, bx, i);
                 self.codegen_argument(bx, op, llargs, &args[i]);
             }
         }
@@ -1813,11 +1803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
         llargs: &mut Vec<Bx::Value>,
         intrinsic: Option<ty::IntrinsicDef>,
-        target: Option<BasicBlock>,
     ) -> ReturnDest<'tcx, Bx::Value> {
-        if target.is_none() {
-            return ReturnDest::Nothing;
-        }
         // If the return is ignored, we can just return a do-nothing `ReturnDest`.
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9ca7d4f8f00..faf1300e473 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -1,15 +1,14 @@
-use std::assert_matches::assert_matches;
 use std::fmt;
 
 use arrayvec::ArrayVec;
 use either::Either;
 use rustc_abi as abi;
 use rustc_abi::{Align, BackendRepr, Size};
-use rustc_middle::bug;
 use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range};
 use rustc_middle::mir::{self, ConstValue};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::{bug, span_bug};
 use tracing::debug;
 
 use super::place::{PlaceRef, PlaceValue};
@@ -352,79 +351,81 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
     pub(crate) fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         &self,
+        fx: &mut FunctionCx<'a, 'tcx, Bx>,
         bx: &mut Bx,
         i: usize,
     ) -> Self {
         let field = self.layout.field(bx.cx(), i);
         let offset = self.layout.fields.offset(i);
 
-        let mut val = match (self.val, self.layout.backend_repr) {
-            // If the field is ZST, it has no data.
-            _ if field.is_zst() => OperandValue::ZeroSized,
-
-            // Newtype of a scalar, scalar pair or vector.
-            (OperandValue::Immediate(_) | OperandValue::Pair(..), _)
-                if field.size == self.layout.size =>
-            {
-                assert_eq!(offset.bytes(), 0);
-                self.val
+        let val = if field.is_zst() {
+            OperandValue::ZeroSized
+        } else if field.size == self.layout.size {
+            assert_eq!(offset.bytes(), 0);
+            if let Some(field_val) = fx.codegen_transmute_operand(bx, *self, field) {
+                field_val
+            } else {
+                // we have to go through memory for things like
+                // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
+                let place = PlaceRef::alloca(bx, field);
+                self.val.store(bx, place.val.with_type(self.layout));
+                bx.load_operand(place).val
             }
-
-            // Extract a scalar component from a pair.
-            (OperandValue::Pair(a_llval, b_llval), BackendRepr::ScalarPair(a, b)) => {
-                if offset.bytes() == 0 {
-                    assert_eq!(field.size, a.size(bx.cx()));
-                    OperandValue::Immediate(a_llval)
-                } else {
-                    assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi));
-                    assert_eq!(field.size, b.size(bx.cx()));
-                    OperandValue::Immediate(b_llval)
+        } else {
+            let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
+                // Extract a scalar component from a pair.
+                (OperandValue::Pair(a_llval, b_llval), BackendRepr::ScalarPair(a, b)) => {
+                    if offset.bytes() == 0 {
+                        assert_eq!(field.size, a.size(bx.cx()));
+                        (Some(a), a_llval)
+                    } else {
+                        assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi));
+                        assert_eq!(field.size, b.size(bx.cx()));
+                        (Some(b), b_llval)
+                    }
                 }
-            }
 
-            // `#[repr(simd)]` types are also immediate.
-            (OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
-                OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
-            }
+                // `#[repr(simd)]` types are also immediate.
+                (OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
+                    (None, bx.extract_element(llval, bx.cx().const_usize(i as u64)))
+                }
 
-            _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
+                _ => {
+                    span_bug!(fx.mir.span, "OperandRef::extract_field({:?}): not applicable", self)
+                }
+            };
+            OperandValue::Immediate(match field.backend_repr {
+                BackendRepr::Vector { .. } => imm,
+                BackendRepr::Scalar(out_scalar) => {
+                    let Some(in_scalar) = in_scalar else {
+                        span_bug!(
+                            fx.mir.span,
+                            "OperandRef::extract_field({:?}): missing input scalar for output scalar",
+                            self
+                        )
+                    };
+                    if in_scalar != out_scalar {
+                        // If the backend and backend_immediate types might differ,
+                        // flip back to the backend type then to the new immediate.
+                        // This avoids nop truncations, but still handles things like
+                        // Bools in union fields needs to be truncated.
+                        let backend = bx.from_immediate(imm);
+                        bx.to_immediate_scalar(backend, out_scalar)
+                    } else {
+                        imm
+                    }
+                }
+                BackendRepr::Memory { sized: true } => {
+                    span_bug!(
+                        fx.mir.span,
+                        "Projecting into a simd type with padding doesn't work; \
+                         See <https://github.com/rust-lang/rust/issues/137108>",
+                    );
+                }
+                BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(),
+            })
         };
 
-        match (&mut val, field.backend_repr) {
-            (OperandValue::ZeroSized, _) => {}
-            (
-                OperandValue::Immediate(llval),
-                BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. },
-            ) => {
-                // Bools in union fields needs to be truncated.
-                *llval = bx.to_immediate(*llval, field);
-            }
-            (OperandValue::Pair(a, b), BackendRepr::ScalarPair(a_abi, b_abi)) => {
-                // Bools in union fields needs to be truncated.
-                *a = bx.to_immediate_scalar(*a, a_abi);
-                *b = bx.to_immediate_scalar(*b, b_abi);
-            }
-            // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
-            (OperandValue::Immediate(llval), BackendRepr::Memory { sized: true }) => {
-                assert_matches!(self.layout.backend_repr, BackendRepr::Vector { .. });
-
-                let llfield_ty = bx.cx().backend_type(field);
-
-                // Can't bitcast an aggregate, so round trip through memory.
-                let llptr = bx.alloca(field.size, field.align.abi);
-                bx.store(*llval, llptr, field.align.abi);
-                *llval = bx.load(llfield_ty, llptr, field.align.abi);
-            }
-            (
-                OperandValue::Immediate(_),
-                BackendRepr::Uninhabited | BackendRepr::Memory { sized: false },
-            ) => {
-                bug!()
-            }
-            (OperandValue::Pair(..), _) => bug!(),
-            (OperandValue::Ref(..), _) => bug!(),
-        }
-
         OperandRef { val, layout: field }
     }
 }
@@ -587,7 +588,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
                                  but tried to access field {f:?} of pointer {o:?}",
                             );
-                            o = o.extract_field(bx, f.index());
+                            o = o.extract_field(self, bx, f.index());
                         }
                         mir::ProjectionElem::Index(_)
                         | mir::ProjectionElem::ConstantIndex { .. } => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index eb4270ffe80..e32d298869b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -1,7 +1,7 @@
 use rustc_abi::Primitive::{Int, Pointer};
 use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
+use rustc_middle::mir::PlaceTy;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, mir};
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 4c5b183cfe9..daa4fa90ed7 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ///
     /// Returns `None` for cases that can't work in that framework, such as for
     /// `Immediate`->`Ref` that needs an `alloc` to get the location.
-    fn codegen_transmute_operand(
+    pub(crate) fn codegen_transmute_operand(
         &mut self,
         bx: &mut Bx,
         operand: OperandRef<'tcx, Bx::Value>,
@@ -260,6 +260,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             OperandValue::Ref(source_place_val) => {
                 assert_eq!(source_place_val.llextra, None);
                 assert_matches!(operand_kind, OperandValueKind::Ref);
+                // The existing alignment is part of `source_place_val`,
+                // so that alignment will be used, not `cast`'s.
                 Some(bx.load_operand(source_place_val.with_type(cast)).val)
             }
             OperandValue::ZeroSized => {
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 48ae000f2c6..2b00ba01946 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,7 +1,7 @@
 use std::assert_matches::assert_matches;
 use std::ops::Deref;
 
-use rustc_abi::{Align, BackendRepr, Scalar, Size, WrappingRange};
+use rustc_abi::{Align, Scalar, Size, WrappingRange};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{Instance, Ty};
@@ -223,13 +223,6 @@ pub trait BuilderMethods<'a, 'tcx>:
     ) -> (Self::Value, Self::Value);
 
     fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
-    fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
-        if let BackendRepr::Scalar(scalar) = layout.backend_repr {
-            self.to_immediate_scalar(val, scalar)
-        } else {
-            val
-        }
-    }
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
 
     fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
@@ -340,6 +333,17 @@ pub trait BuilderMethods<'a, 'tcx>:
     }
 
     fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
+    /// Produces the same value as [`Self::trunc`] (and defaults to that),
+    /// but is UB unless the *zero*-extending the result can reproduce `val`.
+    fn unchecked_utrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
+        self.trunc(val, dest_ty)
+    }
+    /// Produces the same value as [`Self::trunc`] (and defaults to that),
+    /// but is UB unless the *sign*-extending the result can reproduce `val`.
+    fn unchecked_strunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
+        self.trunc(val, dest_ty)
+    }
+
     fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
     fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
     fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index b53c1505f6b..7b706334ed8 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -430,10 +430,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     };
                     let erased_trait_ref =
                         ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
-                    assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
-                        erased_trait_ref,
-                        self.tcx.instantiate_bound_regions_with_erased(b)
-                    )));
+                    assert_eq!(
+                        data_b.principal().map(|b| {
+                            self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b)
+                        }),
+                        Some(erased_trait_ref),
+                    );
                 } else {
                     // In this case codegen would keep using the old vtable. We don't want to do
                     // that as it has the wrong trait. The reason codegen can do this is that
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 66a75113652..c1948e9f31f 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -4,9 +4,6 @@ use either::{Left, Right};
 use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
@@ -17,8 +14,7 @@ use rustc_middle::{mir, span_bug};
 use rustc_session::Limit;
 use rustc_span::Span;
 use rustc_target::callconv::FnAbi;
-use rustc_trait_selection::traits::ObligationCtxt;
-use tracing::{debug, instrument, trace};
+use tracing::{debug, trace};
 
 use super::{
     Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
@@ -320,40 +316,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
-    /// Check if the two things are equal in the current param_env, using an infcx to get proper
-    /// equality checks.
-    #[instrument(level = "trace", skip(self), ret)]
-    pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
-    where
-        T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
-    {
-        // Fast path: compare directly.
-        if a == b {
-            return true;
-        }
-        // Slow path: spin up an inference context to check if these traits are sufficiently equal.
-        let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
-        let ocx = ObligationCtxt::new(&infcx);
-        let cause = ObligationCause::dummy_with_span(self.cur_span());
-        // equate the two trait refs after normalization
-        let a = ocx.normalize(&cause, param_env, a);
-        let b = ocx.normalize(&cause, param_env, b);
-
-        if let Err(terr) = ocx.eq(&cause, param_env, a, b) {
-            trace!(?terr);
-            return false;
-        }
-
-        let errors = ocx.select_all_or_error();
-        if !errors.is_empty() {
-            trace!(?errors);
-            return false;
-        }
-
-        // All good.
-        true
-    }
-
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
     /// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
     /// and is primarily intended for the panic machinery.
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 5d905cff1f2..36da9037e43 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -385,7 +385,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
             (Immediate::Uninit, _) => Immediate::Uninit,
             // If the field is uninhabited, we can forget the data (can happen in ConstProp).
             // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
-            // has an `Uninhabited` variant, which means this case is possible.
+            // has an uninhabited variant, which means this case is possible.
             _ if layout.is_uninhabited() => Immediate::Uninit,
             // the field contains no information, can be left uninit
             // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index 4cfaacebfcd..a5029eea5a7 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -86,21 +86,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
         }
 
+        // This checks whether there is a subtyping relation between the predicates in either direction.
+        // For example:
+        // - casting between `dyn for<'a> Trait<fn(&'a u8)>` and `dyn Trait<fn(&'static u8)>` is OK
+        // - casting between `dyn Trait<for<'a> fn(&'a u8)>` and either of the above is UB
         for (a_pred, b_pred) in std::iter::zip(sorted_vtable, sorted_expected) {
-            let is_eq = match (a_pred.skip_binder(), b_pred.skip_binder()) {
-                (
-                    ty::ExistentialPredicate::Trait(a_data),
-                    ty::ExistentialPredicate::Trait(b_data),
-                ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
+            let a_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, a_pred);
+            let b_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b_pred);
 
-                (
-                    ty::ExistentialPredicate::Projection(a_data),
-                    ty::ExistentialPredicate::Projection(b_data),
-                ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
-
-                _ => false,
-            };
-            if !is_eq {
+            if a_pred != b_pred {
                 throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 0ac34f4633b..40dec0cb39e 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -1264,21 +1264,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
             }
         }
 
-        // *After* all of this, check the ABI. We need to check the ABI to handle
-        // types like `NonNull` where the `Scalar` info is more restrictive than what
-        // the fields say (`rustc_layout_scalar_valid_range_start`).
-        // But in most cases, this will just propagate what the fields say,
-        // and then we want the error to point at the field -- so, first recurse,
-        // then check ABI.
+        // *After* all of this, check further information stored in the layout. We need to check
+        // this to handle types like `NonNull` where the `Scalar` info is more restrictive than what
+        // the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will
+        // just propagate what the fields say, and then we want the error to point at the field --
+        // so, we first recurse, then we do this check.
         //
         // FIXME: We could avoid some redundant checks here. For newtypes wrapping
         // scalars, we do the same check on every "level" (e.g., first we check
         // MyNewtype and then the scalar in there).
+        if val.layout.is_uninhabited() {
+            let ty = val.layout.ty;
+            throw_validation_failure!(self.path, UninhabitedVal { ty });
+        }
         match val.layout.backend_repr {
-            BackendRepr::Uninhabited => {
-                let ty = val.layout.ty;
-                throw_validation_failure!(self.path, UninhabitedVal { ty });
-            }
             BackendRepr::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 79baf91c3ce..6426bca2332 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -111,13 +111,15 @@ fn check_validity_requirement_lax<'tcx>(
     };
 
     // Check the ABI.
-    let valid = match this.backend_repr {
-        BackendRepr::Uninhabited => false, // definitely UB
-        BackendRepr::Scalar(s) => scalar_allows_raw_init(s),
-        BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
-        BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
-        BackendRepr::Memory { .. } => true, // Fields are checked below.
-    };
+    let valid = !this.is_uninhabited() // definitely UB if uninhabited
+        && match this.backend_repr {
+            BackendRepr::Scalar(s) => scalar_allows_raw_init(s),
+            BackendRepr::ScalarPair(s1, s2) => {
+                scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2)
+            }
+            BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
+            BackendRepr::Memory { .. } => true, // Fields are checked below.
+        };
     if !valid {
         // This is definitely not okay.
         return Ok(false);
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 850b052f564..8079212fac5 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -92,7 +92,10 @@ impl<'a, T: Ord> Ord for Interned<'a, T> {
     }
 }
 
-impl<'a, T> Hash for Interned<'a, T> {
+impl<'a, T> Hash for Interned<'a, T>
+where
+    T: Hash,
+{
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
         // Pointer hashing is sufficient, due to the uniqueness constraint.
diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index 08b7d937661..e7bc57c9749 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
 
 use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
 
+/// Signals that represent that we have a bug, and our prompt termination has
+/// been ordered.
+#[rustfmt::skip]
+const KILL_SIGNALS: [(libc::c_int, &str); 3] = [
+    (libc::SIGILL, "SIGILL"),
+    (libc::SIGBUS, "SIGBUS"),
+    (libc::SIGSEGV, "SIGSEGV")
+];
+
 unsafe extern "C" {
     fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int);
 }
@@ -39,8 +48,19 @@ macro raw_errln($tokens:tt) {
 /// # Safety
 ///
 /// Caller must ensure that this function is not re-entered.
-unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
+unsafe extern "C" fn print_stack_trace(signum: libc::c_int) {
     const MAX_FRAMES: usize = 256;
+
+    let signame = {
+        let mut signame = "<unknown>";
+        for sig in KILL_SIGNALS {
+            if sig.0 == signum {
+                signame = sig.1;
+            }
+        }
+        signame
+    };
+
     let stack = unsafe {
         // Reserve data segment so we don't have to malloc in a signal handler, which might fail
         // in incredibly undesirable and unexpected ways due to e.g. the allocator deadlocking
@@ -54,7 +74,8 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
     };
 
     // Just a stack trace is cryptic. Explain what we're doing.
-    raw_errln!("error: rustc interrupted by SIGSEGV, printing backtrace\n");
+    raw_errln!("error: rustc interrupted by {signame}, printing backtrace\n");
+
     let mut written = 1;
     let mut consumed = 0;
     // Begin elaborating return addrs into symbols and writing them directly to stderr
@@ -94,7 +115,7 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
     written += rem.len() + 1;
 
     let random_depth = || 8 * 16; // chosen by random diceroll (2d20)
-    if cyclic || stack.len() > random_depth() {
+    if (cyclic || stack.len() > random_depth()) && signum == libc::SIGSEGV {
         // technically speculation, but assert it with confidence anyway.
         // rustc only arrived in this signal handler because bad things happened
         // and this message is for explaining it's not the programmer's fault
@@ -106,17 +127,22 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
         written += 1;
     }
     raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
-    // get the current stack size WITHOUT blocking and double it
-    let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
-    raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
-    written += 2;
+    written += 1;
+    if signum == libc::SIGSEGV {
+        // get the current stack size WITHOUT blocking and double it
+        let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
+        raw_errln!(
+            "help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}"
+        );
+        written += 1;
+    }
     if written > 24 {
-        // We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
-        raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
+        // We probably just scrolled the earlier "interrupted by {signame}" message off the terminal
+        raw_errln!("note: backtrace dumped due to {signame}! resuming signal");
     };
 }
 
-/// When SIGSEGV is delivered to the process, print a stack trace and then exit.
+/// When one of the KILL signals is delivered to the process, print a stack trace and then exit.
 pub(super) fn install() {
     unsafe {
         let alt_stack_size: usize = min_sigstack_size() + 64 * 1024;
@@ -129,7 +155,9 @@ pub(super) fn install() {
         sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
         sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
         libc::sigemptyset(&mut sa.sa_mask);
-        libc::sigaction(libc::SIGSEGV, &sa, ptr::null_mut());
+        for (signum, _signame) in KILL_SIGNALS {
+            libc::sigaction(signum, &sa, ptr::null_mut());
+        }
     }
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0803.md b/compiler/rustc_error_codes/src/error_codes/E0803.md
new file mode 100644
index 00000000000..4c022688a2d
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0803.md
@@ -0,0 +1,46 @@
+A trait implementation returns a reference without an
+explicit lifetime linking it to `self`.
+It commonly arises in generic trait implementations
+requiring explicit lifetime bounds.
+
+Erroneous code example:
+
+```compile_fail,E0803
+trait DataAccess<T> {
+    fn get_ref(&self) -> T;
+}
+
+struct Container<'a> {
+    value: &'a f64,
+}
+
+// Attempting to implement reference return
+impl<'a> DataAccess<&f64> for Container<'a> {
+    fn get_ref(&self) -> &f64 { // Error: Lifetime mismatch
+        self.value
+    }
+}
+```
+
+The trait method returns &f64 requiring an independent lifetime
+The struct Container<'a> carries lifetime parameter 'a
+The compiler cannot verify if the returned reference satisfies 'a constraints
+Solution
+Explicitly bind lifetimes to clarify constraints:
+```
+// Modified trait with explicit lifetime binding
+trait DataAccess<'a, T> {
+    fn get_ref(&'a self) -> T;
+}
+
+struct Container<'a> {
+    value: &'a f64,
+}
+
+// Correct implementation (bound lifetimes)
+impl<'a> DataAccess<'a, &'a f64> for Container<'a> {
+    fn get_ref(&'a self) -> &'a f64 {
+        self.value
+    }
+}
+```
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index e970b16f610..098ca42be2b 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -546,6 +546,7 @@ E0799: 0799,
 E0800: 0800,
 E0801: 0801,
 E0802: 0802,
+E0803: 0803,
         );
     )
 }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5560d087e96..47d5976be09 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -387,6 +387,8 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
 
 hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
 
+hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}`
+
 hir_analysis_not_supported_delegation = {$descr}
     .label = callee defined here
 
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 0dd8296e66c..c193aad2afd 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2104,18 +2104,21 @@ pub(super) fn check_type_bounds<'tcx>(
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
 
-    let mut obligations: Vec<_> = tcx
-        .explicit_item_bounds(trait_ty.def_id)
-        .iter_instantiated_copied(tcx, rebased_args)
-        .map(|(concrete_ty_bound, span)| {
-            debug!(?concrete_ty_bound);
-            traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
-        })
-        .collect();
+    let mut obligations: Vec<_> = util::elaborate(
+        tcx,
+        tcx.explicit_item_bounds(trait_ty.def_id).iter_instantiated_copied(tcx, rebased_args).map(
+            |(concrete_ty_bound, span)| {
+                debug!(?concrete_ty_bound);
+                traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
+            },
+        ),
+    )
+    .collect();
 
     // Only in a const implementation do we need to check that the `~const` item bounds hold.
     if tcx.is_conditionally_const(impl_ty_def_id) {
-        obligations.extend(
+        obligations.extend(util::elaborate(
+            tcx,
             tcx.explicit_implied_const_bounds(trait_ty.def_id)
                 .iter_instantiated_copied(tcx, rebased_args)
                 .map(|(c, span)| {
@@ -2126,7 +2129,7 @@ pub(super) fn check_type_bounds<'tcx>(
                         c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
                     )
                 }),
-        );
+        ));
     }
     debug!(item_bounds=?obligations);
 
@@ -2134,26 +2137,19 @@ pub(super) fn check_type_bounds<'tcx>(
     // 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 trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
-    let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
     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 = if infcx.next_trait_solver() {
-            obligation.predicate.fold_with(&mut ReplaceTy {
-                tcx,
-                from: trait_projection_ty,
-                to: impl_identity_ty,
-            })
-        } else {
-            ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
-        };
-        debug!(?normalized_predicate);
-        obligation.predicate = normalized_predicate;
-
-        ocx.register_obligation(obligation);
+    for obligation in &mut obligations {
+        match ocx.deeply_normalize(&normalize_cause, normalize_param_env, obligation.predicate) {
+            Ok(pred) => obligation.predicate = pred,
+            Err(e) => {
+                return Err(infcx.err_ctxt().report_fulfillment_errors(e));
+            }
+        }
     }
+
     // Check that all obligations are satisfied by the implementation's
     // version.
+    ocx.register_obligations(obligations);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
         let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
@@ -2165,22 +2161,6 @@ pub(super) fn check_type_bounds<'tcx>(
     ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
 }
 
-struct ReplaceTy<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    from: Ty<'tcx>,
-    to: Ty<'tcx>,
-}
-
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if self.from == ty { self.to } else { ty.super_fold_with(self) }
-    }
-}
-
 /// Install projection predicates that allow GATs to project to their own
 /// definition types. This is not allowed in general in cases of default
 /// associated types in trait definitions, or when specialization is involved,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index edfa897860b..f98504e19de 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -16,7 +16,6 @@ use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
 use rustc_macros::LintDiagnostic;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
@@ -143,33 +142,7 @@ where
         return Ok(());
     }
 
-    let is_bevy = 'is_bevy: {
-        // We don't want to emit this for dependents of Bevy, for now.
-        // See #119956
-        let is_bevy_paramset = |def: ty::AdtDef<'_>| {
-            let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did));
-            adt_did.contains("ParamSet")
-        };
-        for ty in assumed_wf_types.iter() {
-            match ty.kind() {
-                ty::Adt(def, _) => {
-                    if is_bevy_paramset(*def) {
-                        break 'is_bevy true;
-                    }
-                }
-                ty::Ref(_, ty, _) => match ty.kind() {
-                    ty::Adt(def, _) => {
-                        if is_bevy_paramset(*def) {
-                            break 'is_bevy true;
-                        }
-                    }
-                    _ => {}
-                },
-                _ => {}
-            }
-        }
-        false
-    };
+    let is_bevy = assumed_wf_types.visit_with(&mut ContainsBevyParamSet { tcx }).is_break();
 
     // If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
     // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
@@ -194,6 +167,31 @@ where
     }
 }
 
+struct ContainsBevyParamSet<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        // We only care to match `ParamSet<T>` or `&ParamSet<T>`.
+        match t.kind() {
+            ty::Adt(def, _) => {
+                if self.tcx.item_name(def.did()) == sym::ParamSet
+                    && self.tcx.crate_name(def.did().krate) == sym::bevy_ecs
+                {
+                    return ControlFlow::Break(());
+                }
+            }
+            ty::Ref(_, ty, _) => ty.visit_with(self)?,
+            _ => {}
+        }
+
+        ControlFlow::Continue(())
+    }
+}
+
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
     let node = tcx.hir_node_by_def_id(def_id);
     let mut res = match node {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 14ea10461cb..1a0b0edb257 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1417,6 +1417,15 @@ pub(crate) struct CrossCrateTraitsDefined {
     pub traits: String,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_no_variant_named, code = E0599)]
+pub struct NoVariantNamed<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ident: Ident,
+    pub ty: Ty<'tcx>,
+}
+
 // FIXME(fmease): Deduplicate:
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index ec8343bb2bf..e9b99caf737 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -53,7 +53,9 @@ use rustc_type_ir::Upcast;
 use tracing::{debug, instrument};
 
 use crate::check::check_abi_fn_ptr;
-use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType};
+use crate::errors::{
+    AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed,
+};
 use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -1205,14 +1207,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     let msg = format!("expected type, found variant `{assoc_ident}`");
                     self.dcx().span_err(span, msg)
                 } else if qself_ty.is_enum() {
-                    let mut err = struct_span_code_err!(
-                        self.dcx(),
-                        assoc_ident.span,
-                        E0599,
-                        "no variant named `{}` found for enum `{}`",
-                        assoc_ident,
-                        qself_ty,
-                    );
+                    let mut err = self.dcx().create_err(NoVariantNamed {
+                        span: assoc_ident.span,
+                        ident: assoc_ident,
+                        ty: qself_ty,
+                    });
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
                     if let Some(variant_name) = find_best_match_for_name(
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 66d7c9377ed..0859a39b155 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -92,6 +92,7 @@ mod impl_wf_check;
 mod outlives;
 mod variance;
 
+pub use errors::NoVariantNamed;
 use rustc_abi::ExternAbi;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 1f5acaa58a9..0331a20f95b 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2021"
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index b46d7c49063..1c63b8b3655 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -19,6 +19,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
+use rustc_hir_analysis::NoVariantNamed;
 use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
 use rustc_infer::infer;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
@@ -3837,15 +3838,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .iter_enumerated()
                         .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
                     else {
-                        type_error_struct!(
-                            self.dcx(),
-                            ident.span,
-                            container,
-                            E0599,
-                            "no variant named `{ident}` found for enum `{container}`",
-                        )
-                        .with_span_label(field.span, "variant not found")
-                        .emit();
+                        self.dcx()
+                            .create_err(NoVariantNamed { span: ident.span, ident, ty: container })
+                            .with_span_label(field.span, "variant not found")
+                            .emit_unless(container.references_error());
                         break;
                     };
                     let Some(&subfield) = fields.next() else {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index cd07666ca6c..e63cc090993 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -230,10 +230,19 @@ enum InheritedRefMatchRule {
     /// underlying type is not a reference type, the inherited reference will be consumed.
     EatInner,
     /// When the underlying type is a reference type, reference patterns consume both layers of
-    /// reference, i.e. they both reset the binding mode and consume the reference type. Reference
-    /// patterns are not permitted when there is no underlying reference type, i.e. they can't eat
-    /// only an inherited reference. This is the current stable Rust behavior.
-    EatBoth,
+    /// reference, i.e. they both reset the binding mode and consume the reference type.
+    EatBoth {
+        /// If `true`, an inherited reference will be considered when determining whether a reference
+        /// pattern matches a given type:
+        /// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
+        /// - If the underlying type is a reference, a reference pattern matches if it can eat either one
+        ///    of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
+        ///    underlying type is `&mut` or the inherited reference is `&mut`.
+        /// If `false`, a reference pattern is only matched against the underlying type.
+        /// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
+        /// `ref_pat_eat_one_layer_2024_structural` feature gates.
+        consider_inherited_ref: bool,
+    },
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -259,10 +268,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             } else {
                 // Currently, matching against an inherited ref on edition 2024 is an error.
                 // Use `EatBoth` as a fallback to be similar to stable Rust.
-                InheritedRefMatchRule::EatBoth
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
             }
         } else {
-            InheritedRefMatchRule::EatBoth
+            InheritedRefMatchRule::EatBoth {
+                consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
+                    || self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
+            }
         }
     }
 
@@ -835,20 +847,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        ident.span,
+                        't', // last char of `mut`
                         def_br_mutbl,
                     );
                     BindingMode(ByRef::No, Mutability::Mut)
                 }
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
-            BindingMode(ByRef::Yes(_), _) => {
+            BindingMode(ByRef::Yes(user_br_mutbl), _) => {
                 if let ByRef::Yes(def_br_mutbl) = def_br {
                     // `ref`/`ref mut` overrides the binding mode on edition <= 2021
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        ident.span,
+                        match user_br_mutbl {
+                            Mutability::Not => 'f', // last char of `ref`
+                            Mutability::Mut => 't', // last char of `ref mut`
+                        },
                         def_br_mutbl,
                     );
                 }
@@ -2371,6 +2386,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // NB: This assumes that `&` patterns can match against mutable
                             // references (RFC 3627, Rule 5). If we implement a pattern typing
                             // ruleset with Rule 4 but not Rule 5, we'll need to check that here.
+                            // FIXME(ref_pat_eat_one_layer_2024_structural): If we already tried
+                            // matching the real reference, the error message should explain that
+                            // falling back to the inherited reference didn't work. This should be
+                            // the same error as the old-Edition version below.
                             debug_assert!(ref_pat_matches_mut_ref);
                             self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
                         }
@@ -2381,13 +2400,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         return expected;
                     }
                 }
-                InheritedRefMatchRule::EatBoth => {
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
                     // Reset binding mode on old editions
                     pat_info.binding_mode = ByRef::No;
+
+                    if let ty::Ref(_, inner_ty, _) = *expected.kind() {
+                        // Consume both the inherited and inner references.
+                        if pat_mutbl.is_mut() && inh_mut.is_mut() {
+                            // As a special case, a `&mut` reference pattern will be able to match
+                            // against a reference type of any mutability if the inherited ref is
+                            // mutable. Since this allows us to match against a shared reference
+                            // type, we refer to this as "falling back" to matching the inherited
+                            // reference, though we consume the real reference as well. We handle
+                            // this here to avoid adding this case to the common logic below.
+                            self.check_pat(inner, inner_ty, pat_info);
+                            return expected;
+                        } else {
+                            // Otherwise, use the common logic below for matching the inner
+                            // reference type.
+                            // FIXME(ref_pat_eat_one_layer_2024_structural): If this results in a
+                            // mutability mismatch, the error message should explain that falling
+                            // back to the inherited reference didn't work. This should be the same
+                            // error as the Edition 2024 version above.
+                        }
+                    } else {
+                        // The expected type isn't a reference type, so only match against the
+                        // inherited reference.
+                        if pat_mutbl > inh_mut {
+                            // We can't match a lone inherited shared reference with `&mut`.
+                            self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
+                        }
+
+                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+                        self.check_pat(inner, expected, pat_info);
+                        return expected;
+                    }
+                }
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
+                    // Reset binding mode on stable Rust. This will be a type error below if
+                    // `expected` is not a reference type.
+                    pat_info.binding_mode = ByRef::No;
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        inner.span,
+                        match pat_mutbl {
+                            Mutability::Not => '&', // last char of `&`
+                            Mutability::Mut => 't', // last char of `&mut`
+                        },
                         inh_mut,
                     )
                 }
@@ -2779,18 +2838,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat_id: HirId,
         subpat: &'tcx Pat<'tcx>,
-        cutoff_span: Span,
+        final_char: char,
         def_br_mutbl: Mutability,
     ) {
         // Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
-        // If the subpattern's span is is from an expansion, the emitted label will not be trimmed.
-        let source_map = self.tcx.sess.source_map();
-        let cutoff_span = source_map
-            .span_extend_prev_while(cutoff_span, |c| c.is_whitespace() || c == '(')
-            .unwrap_or(cutoff_span);
-        // Ensure we use the syntax context and thus edition of `subpat.span`; this will be a hard
-        // error if the subpattern is of edition >= 2024.
-        let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt());
+        let from_expansion = subpat.span.from_expansion();
+        let trimmed_span = if from_expansion {
+            // If the subpattern is from an expansion, highlight the whole macro call instead.
+            subpat.span
+        } else {
+            let trimmed = self.tcx.sess.source_map().span_through_char(subpat.span, final_char);
+            // The edition of the trimmed span should be the same as `subpat.span`; this will be a
+            // a hard error if the subpattern is of edition >= 2024. We set it manually to be sure:
+            trimmed.with_ctxt(subpat.span.ctxt())
+        };
 
         let mut typeck_results = self.typeck_results.borrow_mut();
         let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
@@ -2806,31 +2867,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
         });
 
+        let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
+            info.bad_modifiers = true;
+            // If the user-provided binding modifier doesn't match the default binding mode, we'll
+            // need to suggest reference patterns, which can affect other bindings.
+            // For simplicity, we opt to suggest making the pattern fully explicit.
+            info.suggest_eliding_modes &=
+                user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
+            "binding modifier"
+        } else {
+            info.bad_ref_pats = true;
+            // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
+            // suggest adding them instead, which can affect the types assigned to bindings.
+            // As such, we opt to suggest making the pattern fully explicit.
+            info.suggest_eliding_modes = false;
+            "reference pattern"
+        };
         // Only provide a detailed label if the problematic subpattern isn't from an expansion.
         // In the case that it's from a macro, we'll add a more detailed note in the emitter.
-        let from_expansion = subpat.span.from_expansion();
         let primary_label = if from_expansion {
+            // We can't suggest eliding modifiers within expansions.
+            info.suggest_eliding_modes = false;
             // NB: This wording assumes the only expansions that can produce problematic reference
             // patterns and bindings are macros. If a desugaring or AST pass is added that can do
             // so, we may want to inspect the span's source callee or macro backtrace.
             "occurs within macro expansion".to_owned()
         } else {
-            let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
-                info.bad_modifiers |= true;
-                // If the user-provided binding modifier doesn't match the default binding mode, we'll
-                // need to suggest reference patterns, which can affect other bindings.
-                // For simplicity, we opt to suggest making the pattern fully explicit.
-                info.suggest_eliding_modes &=
-                    user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
-                "binding modifier"
-            } else {
-                info.bad_ref_pats |= true;
-                // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
-                // suggest adding them instead, which can affect the types assigned to bindings.
-                // As such, we opt to suggest making the pattern fully explicit.
-                info.suggest_eliding_modes = false;
-                "reference pattern"
-            };
             let dbm_str = match def_br_mutbl {
                 Mutability::Not => "ref",
                 Mutability::Mut => "ref mut",
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 6d1a2d3de9e..baf5dbbfd42 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -8,7 +8,6 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 31f585c0c9e..b346e193d0b 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,8 +1,7 @@
 use std::fmt;
 
-use rustc_ast_ir::try_visit;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor, try_visit};
 use rustc_middle::ty::{self, TyCtxt};
 
 use crate::traits;
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c8de5e87753..044a613dad6 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -641,6 +641,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(USAGE_OF_QUALIFIED_TY),
             LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
+            LintId::of(USAGE_OF_TYPE_IR_INHERENT),
             LintId::of(BAD_OPT_ACCESS),
             LintId::of(SPAN_USE_EQ_CTXT),
         ],
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index 527ca26c0eb..a7906d50d0f 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -36,12 +36,12 @@ pub(super) fn type_visitable_derive(
     s.add_bounds(synstructure::AddBounds::Generics);
     let body_visit = s.each(|bind| {
         quote! {
-            match ::rustc_ast_ir::visit::VisitorResult::branch(
+            match ::rustc_middle::ty::visit::VisitorResult::branch(
                 ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
             ) {
                 ::core::ops::ControlFlow::Continue(()) => {},
                 ::core::ops::ControlFlow::Break(r) => {
-                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                    return ::rustc_middle::ty::visit::VisitorResult::from_residual(r);
                 },
             }
         }
@@ -56,7 +56,7 @@ pub(super) fn type_visitable_derive(
                 __visitor: &mut __V
             ) -> __V::Result {
                 match *self { #body_visit }
-                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                <__V::Result as ::rustc_middle::ty::visit::VisitorResult>::output()
             }
         },
     )
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 1b6a174c093..389c861c3b5 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -14,7 +14,6 @@ rustc_abi = { path = "../rustc_abi" }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" } # Used for intra-doc links
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index dcfa81dab25..0b3c0be1a4e 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -37,9 +37,6 @@ middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty}
 middle_bounds_check =
     index out of bounds: the length is {$len} but the index is {$index}
 
-middle_cannot_be_normalized =
-    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
-
 middle_conflict_types =
     this expression supplies two conflicting concrete types for the same opaque type
 
@@ -52,9 +49,6 @@ middle_const_eval_non_int =
 middle_const_not_used_in_type_alias =
     const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
 
-middle_cycle =
-    a cycle occurred during layout computation
-
 middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note ->
         [true] : {$note}
         *[other] {""}
@@ -78,9 +72,23 @@ middle_erroneous_constant = erroneous constant encountered
 middle_failed_writing_file =
     failed to write file {$path}: {$error}"
 
+middle_layout_cycle =
+    a cycle occurred during layout computation
+
+middle_layout_normalization_failure =
+    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
+
 middle_layout_references_error =
     the type has an unknown layout
 
+middle_layout_size_overflow =
+    values of the type `{$ty}` are too big for the target architecture
+
+middle_layout_too_generic = the type `{$ty}` does not have a fixed layout
+
+middle_layout_unknown =
+    the type `{$ty}` has an unknown layout
+
 middle_opaque_hidden_type_mismatch =
     concrete type differs from previous defining opaque type use
     .label = expected `{$self_ty}`, got `{$other_ty}`
@@ -98,16 +106,8 @@ middle_strict_coherence_needs_negative_coherence =
     to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
     .label = due to this attribute
 
-middle_too_generic = `{$ty}` does not have a fixed size
-
 middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
 
-middle_unknown_layout =
-    the type `{$ty}` has an unknown layout
-
 middle_unsupported_union = we don't support unions yet: '{$ty_name}'
 
-middle_values_too_big =
-    values of the type `{$ty}` are too big for the target architecture
-
 middle_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index c53e3d54cc4..be8a3403ba9 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -132,19 +132,19 @@ impl fmt::Debug for CustomSubdiagnostic<'_> {
 
 #[derive(Diagnostic)]
 pub enum LayoutError<'tcx> {
-    #[diag(middle_unknown_layout)]
+    #[diag(middle_layout_unknown)]
     Unknown { ty: Ty<'tcx> },
 
-    #[diag(middle_too_generic)]
+    #[diag(middle_layout_too_generic)]
     TooGeneric { ty: Ty<'tcx> },
 
-    #[diag(middle_values_too_big)]
+    #[diag(middle_layout_size_overflow)]
     Overflow { ty: Ty<'tcx> },
 
-    #[diag(middle_cannot_be_normalized)]
+    #[diag(middle_layout_normalization_failure)]
     NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
 
-    #[diag(middle_cycle)]
+    #[diag(middle_layout_cycle)]
     Cycle,
 
     #[diag(middle_layout_references_error)]
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index b3064d8fe25..b5f3a0e1482 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -83,7 +83,7 @@ macro_rules! TrivialTypeTraversalImpls {
                     _: &mut F)
                     -> F::Result
                 {
-                    <F::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                    <F::Result as ::rustc_middle::ty::visit::VisitorResult>::output()
                 }
             }
         )+
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 8861e31b099..743812e3a20 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -5,7 +5,6 @@ use std::{convert, fmt, mem, ops};
 
 use either::Either;
 use rustc_abi::{Align, Size, VariantIdx, WrappingRange};
-use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
@@ -16,7 +15,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
 use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
 use crate::error;
 use crate::mir::{ConstAlloc, ConstValue};
-use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls};
+use crate::ty::{self, Mutability, Ty, TyCtxt, ValTree, layout, tls};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub enum ErrorHandled {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index cc22cabcb3e..71fed4b3e1e 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -4,8 +4,8 @@
 
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Formatter};
+use std::iter;
 use std::ops::{Index, IndexMut};
-use std::{iter, mem};
 
 pub use basic_blocks::{BasicBlocks, SwitchTargetValue};
 use either::Either;
@@ -32,7 +32,6 @@ use tracing::{debug, trace};
 pub use self::query::*;
 use self::visit::TyContext;
 use crate::mir::interpret::{AllocRange, Scalar};
-use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
 use crate::ty::visit::TypeVisitableExt;
@@ -53,7 +52,6 @@ pub mod pretty;
 mod query;
 mod statement;
 mod syntax;
-pub mod tcx;
 mod terminator;
 
 pub mod traversal;
@@ -1365,70 +1363,6 @@ impl<'tcx> BasicBlockData<'tcx> {
         self.terminator.as_mut().expect("invalid terminator state")
     }
 
-    pub fn retain_statements<F>(&mut self, mut f: F)
-    where
-        F: FnMut(&mut Statement<'_>) -> bool,
-    {
-        for s in &mut self.statements {
-            if !f(s) {
-                s.make_nop();
-            }
-        }
-    }
-
-    pub fn expand_statements<F, I>(&mut self, mut f: F)
-    where
-        F: FnMut(&mut Statement<'tcx>) -> Option<I>,
-        I: iter::TrustedLen<Item = Statement<'tcx>>,
-    {
-        // Gather all the iterators we'll need to splice in, and their positions.
-        let mut splices: Vec<(usize, I)> = vec![];
-        let mut extra_stmts = 0;
-        for (i, s) in self.statements.iter_mut().enumerate() {
-            if let Some(mut new_stmts) = f(s) {
-                if let Some(first) = new_stmts.next() {
-                    // We can already store the first new statement.
-                    *s = first;
-
-                    // Save the other statements for optimized splicing.
-                    let remaining = new_stmts.size_hint().0;
-                    if remaining > 0 {
-                        splices.push((i + 1 + extra_stmts, new_stmts));
-                        extra_stmts += remaining;
-                    }
-                } else {
-                    s.make_nop();
-                }
-            }
-        }
-
-        // Splice in the new statements, from the end of the block.
-        // FIXME(eddyb) This could be more efficient with a "gap buffer"
-        // where a range of elements ("gap") is left uninitialized, with
-        // splicing adding new elements to the end of that gap and moving
-        // existing elements from before the gap to the end of the gap.
-        // For now, this is safe code, emulating a gap but initializing it.
-        let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
-        self.statements.resize(
-            gap.end,
-            Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
-        );
-        for (splice_start, new_stmts) in splices.into_iter().rev() {
-            let splice_end = splice_start + new_stmts.size_hint().0;
-            while gap.end > splice_end {
-                gap.start -= 1;
-                gap.end -= 1;
-                self.statements.swap(gap.start, gap.end);
-            }
-            self.statements.splice(splice_start..splice_end, new_stmts);
-            gap.end = splice_start;
-        }
-    }
-
-    pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
-        if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
-    }
-
     /// Does the block have no statements and an unreachable terminator?
     #[inline]
     pub fn is_empty_unreachable(&self) -> bool {
@@ -1560,7 +1494,7 @@ pub struct SourceScopeLocalData {
 /// &'static str`.
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UserTypeProjections {
-    pub contents: Vec<(UserTypeProjection, Span)>,
+    pub contents: Vec<UserTypeProjection>,
 }
 
 impl<'tcx> UserTypeProjections {
@@ -1572,26 +1506,17 @@ impl<'tcx> UserTypeProjections {
         self.contents.is_empty()
     }
 
-    pub fn projections_and_spans(
-        &self,
-    ) -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator {
-        self.contents.iter()
-    }
-
     pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
-        self.contents.iter().map(|&(ref user_type, _span)| user_type)
+        self.contents.iter()
     }
 
-    pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
-        self.contents.push((user_ty.clone(), span));
+    pub fn push_user_type(mut self, base_user_type: UserTypeAnnotationIndex) -> Self {
+        self.contents.push(UserTypeProjection { base: base_user_type, projs: vec![] });
         self
     }
 
-    fn map_projections(
-        mut self,
-        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
-    ) -> Self {
-        self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
+    fn map_projections(mut self, f: impl FnMut(UserTypeProjection) -> UserTypeProjection) -> Self {
+        self.contents = self.contents.into_iter().map(f).collect();
         self
     }
 
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index d345c99f902..595a5e548b0 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -1,7 +1,10 @@
 //! Functionality for statements, operands, places, and things that appear in them.
 
+use tracing::{debug, instrument};
+
 use super::interpret::GlobalAlloc;
 use super::*;
+use crate::ty::CoroutineArgsExt;
 
 ///////////////////////////////////////////////////////////////////////////
 // Statements
@@ -19,15 +22,6 @@ impl Statement<'_> {
     pub fn make_nop(&mut self) {
         self.kind = StatementKind::Nop
     }
-
-    /// Changes a statement to a nop and returns the original statement.
-    #[must_use = "If you don't need the statement, use `make_nop` instead"]
-    pub fn replace_nop(&mut self) -> Self {
-        Statement {
-            source_info: self.source_info,
-            kind: mem::replace(&mut self.kind, StatementKind::Nop),
-        }
-    }
 }
 
 impl<'tcx> StatementKind<'tcx> {
@@ -49,6 +43,162 @@ impl<'tcx> StatementKind<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // Places
 
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+pub struct PlaceTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    /// Downcast to a particular variant of an enum or a coroutine, if included.
+    pub variant_index: Option<VariantIdx>,
+}
+
+// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
+#[cfg(target_pointer_width = "64")]
+rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16);
+
+impl<'tcx> PlaceTy<'tcx> {
+    #[inline]
+    pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
+        PlaceTy { ty, variant_index: None }
+    }
+
+    /// `place_ty.field_ty(tcx, f)` computes the type of a given field.
+    ///
+    /// Most clients of `PlaceTy` can instead just extract the relevant type
+    /// directly from their `PlaceElem`, but some instances of `ProjectionElem<V, T>`
+    /// do not carry a `Ty` for `T`.
+    ///
+    /// Note that the resulting type has not been normalized.
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
+        if let Some(variant_index) = self.variant_index {
+            match *self.ty.kind() {
+                ty::Adt(adt_def, args) if adt_def.is_enum() => {
+                    adt_def.variant(variant_index).fields[f].ty(tcx, args)
+                }
+                ty::Coroutine(def_id, args) => {
+                    let mut variants = args.as_coroutine().state_tys(def_id, tcx);
+                    let Some(mut variant) = variants.nth(variant_index.into()) else {
+                        bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
+                    };
+
+                    variant
+                        .nth(f.index())
+                        .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
+                }
+                _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
+            }
+        } else {
+            match self.ty.kind() {
+                ty::Adt(adt_def, args) if !adt_def.is_enum() => {
+                    adt_def.non_enum_variant().fields[f].ty(tcx, args)
+                }
+                ty::Closure(_, args) => args
+                    .as_closure()
+                    .upvar_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                ty::CoroutineClosure(_, args) => args
+                    .as_coroutine_closure()
+                    .upvar_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                // Only prefix fields (upvars and current state) are
+                // accessible without a variant index.
+                ty::Coroutine(_, args) => args
+                    .as_coroutine()
+                    .prefix_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                ty::Tuple(tys) => tys
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                _ => bug!("can't project out of {self:?}"),
+            }
+        }
+    }
+
+    pub fn multi_projection_ty(
+        self,
+        tcx: TyCtxt<'tcx>,
+        elems: &[PlaceElem<'tcx>],
+    ) -> PlaceTy<'tcx> {
+        elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
+    }
+
+    /// Convenience wrapper around `projection_ty_core` for
+    /// `PlaceElem`, where we can just use the `Ty` that is already
+    /// stored inline on field projection elems.
+    pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
+        self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
+    }
+
+    /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
+    /// projects `place_ty` onto `elem`, returning the appropriate
+    /// `Ty` or downcast variant corresponding to that projection.
+    /// The `handle_field` callback must map a `FieldIdx` to its `Ty`,
+    /// (which should be trivial when `T` = `Ty`).
+    pub fn projection_ty_core<V, T>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        elem: &ProjectionElem<V, T>,
+        mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
+        mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
+    ) -> PlaceTy<'tcx>
+    where
+        V: ::std::fmt::Debug,
+        T: ::std::fmt::Debug + Copy,
+    {
+        if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
+            bug!("cannot use non field projection on downcasted place")
+        }
+        let answer = match *elem {
+            ProjectionElem::Deref => {
+                let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
+                    bug!("deref projection of non-dereferenceable ty {:?}", self)
+                });
+                PlaceTy::from_ty(ty)
+            }
+            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
+                PlaceTy::from_ty(self.ty.builtin_index().unwrap())
+            }
+            ProjectionElem::Subslice { from, to, from_end } => {
+                PlaceTy::from_ty(match self.ty.kind() {
+                    ty::Slice(..) => self.ty,
+                    ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
+                    ty::Array(inner, size) if from_end => {
+                        let size = size
+                            .try_to_target_usize(tcx)
+                            .expect("expected subslice projection on fixed-size array");
+                        let len = size - from - to;
+                        Ty::new_array(tcx, *inner, len)
+                    }
+                    _ => bug!("cannot subslice non-array type: `{:?}`", self),
+                })
+            }
+            ProjectionElem::Downcast(_name, index) => {
+                PlaceTy { ty: self.ty, variant_index: Some(index) }
+            }
+            ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
+            ProjectionElem::OpaqueCast(ty) => {
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+            }
+            ProjectionElem::Subtype(ty) => {
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+            }
+
+            // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
+            ProjectionElem::UnwrapUnsafeBinder(ty) => {
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+            }
+        };
+        debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
+        answer
+    }
+}
+
 impl<V, T> ProjectionElem<V, T> {
     /// Returns `true` if the target of this projection may refer to a different region of memory
     /// than the base.
@@ -192,6 +342,25 @@ impl<'tcx> Place<'tcx> {
 
         self.as_ref().project_deeper(more_projections, tcx)
     }
+
+    pub fn ty_from<D: ?Sized>(
+        local: Local,
+        projection: &[PlaceElem<'tcx>],
+        local_decls: &D,
+        tcx: TyCtxt<'tcx>,
+    ) -> PlaceTy<'tcx>
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection)
+    }
+
+    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        Place::ty_from(self.local, self.projection, local_decls, tcx)
+    }
 }
 
 impl From<Local> for Place<'_> {
@@ -294,6 +463,13 @@ impl<'tcx> PlaceRef<'tcx> {
 
         Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
     }
+
+    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        Place::ty_from(self.local, self.projection, local_decls, tcx)
+    }
 }
 
 impl From<Local> for PlaceRef<'_> {
@@ -388,6 +564,28 @@ impl<'tcx> Operand<'tcx> {
         let const_ty = self.constant()?.const_.ty();
         if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None }
     }
+
+    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        match self {
+            &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
+            Operand::Constant(c) => c.const_.ty(),
+        }
+    }
+
+    pub fn span<D: ?Sized>(&self, local_decls: &D) -> Span
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        match self {
+            &Operand::Copy(ref l) | &Operand::Move(ref l) => {
+                local_decls.local_decls()[l.local].source_info.span
+            }
+            Operand::Constant(c) => c.span,
+        }
+    }
 }
 
 impl<'tcx> ConstOperand<'tcx> {
@@ -413,6 +611,11 @@ impl<'tcx> ConstOperand<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 /// Rvalues
 
+pub enum RvalueInitializationState {
+    Shallow,
+    Deep,
+}
+
 impl<'tcx> Rvalue<'tcx> {
     /// Returns true if rvalue can be safely removed when the result is unused.
     #[inline]
@@ -452,6 +655,70 @@ impl<'tcx> Rvalue<'tcx> {
             | Rvalue::WrapUnsafeBinder(_, _) => true,
         }
     }
+
+    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        match *self {
+            Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
+            Rvalue::Repeat(ref operand, count) => {
+                Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count)
+            }
+            Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
+            Rvalue::Ref(reg, bk, ref place) => {
+                let place_ty = place.ty(local_decls, tcx).ty;
+                Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
+            }
+            Rvalue::RawPtr(kind, ref place) => {
+                let place_ty = place.ty(local_decls, tcx).ty;
+                Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
+            }
+            Rvalue::Len(..) => tcx.types.usize,
+            Rvalue::Cast(.., ty) => ty,
+            Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
+                let lhs_ty = lhs.ty(local_decls, tcx);
+                let rhs_ty = rhs.ty(local_decls, tcx);
+                op.ty(tcx, lhs_ty, rhs_ty)
+            }
+            Rvalue::UnaryOp(op, ref operand) => {
+                let arg_ty = operand.ty(local_decls, tcx);
+                op.ty(tcx, arg_ty)
+            }
+            Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
+                tcx.types.usize
+            }
+            Rvalue::NullaryOp(NullOp::ContractChecks, _)
+            | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
+            Rvalue::Aggregate(ref ak, ref ops) => match **ak {
+                AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
+                AggregateKind::Tuple => {
+                    Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
+                }
+                AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
+                AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
+                AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args),
+                AggregateKind::CoroutineClosure(did, args) => {
+                    Ty::new_coroutine_closure(tcx, did, args)
+                }
+                AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability),
+            },
+            Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
+            Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,
+            Rvalue::WrapUnsafeBinder(_, ty) => ty,
+        }
+    }
+
+    #[inline]
+    /// Returns `true` if this rvalue is deeply initialized (most rvalues) or
+    /// whether its only shallowly initialized (`Rvalue::Box`).
+    pub fn initialization_state(&self) -> RvalueInitializationState {
+        match *self {
+            Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow,
+            _ => RvalueInitializationState::Deep,
+        }
+    }
 }
 
 impl BorrowKind {
@@ -474,4 +741,124 @@ impl BorrowKind {
             BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true,
         }
     }
+
+    pub fn to_mutbl_lossy(self) -> hir::Mutability {
+        match self {
+            BorrowKind::Mut { .. } => hir::Mutability::Mut,
+            BorrowKind::Shared => hir::Mutability::Not,
+
+            // We have no type corresponding to a shallow borrow, so use
+            // `&` as an approximation.
+            BorrowKind::Fake(_) => hir::Mutability::Not,
+        }
+    }
+}
+
+impl<'tcx> UnOp {
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
+        match self {
+            UnOp::Not | UnOp::Neg => arg_ty,
+            UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
+        }
+    }
+}
+
+impl<'tcx> BinOp {
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> {
+        // FIXME: handle SIMD correctly
+        match self {
+            &BinOp::Add
+            | &BinOp::AddUnchecked
+            | &BinOp::Sub
+            | &BinOp::SubUnchecked
+            | &BinOp::Mul
+            | &BinOp::MulUnchecked
+            | &BinOp::Div
+            | &BinOp::Rem
+            | &BinOp::BitXor
+            | &BinOp::BitAnd
+            | &BinOp::BitOr => {
+                // these should be integers or floats of the same size.
+                assert_eq!(lhs_ty, rhs_ty);
+                lhs_ty
+            }
+            &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
+                // these should be integers of the same size.
+                assert_eq!(lhs_ty, rhs_ty);
+                Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
+            }
+            &BinOp::Shl
+            | &BinOp::ShlUnchecked
+            | &BinOp::Shr
+            | &BinOp::ShrUnchecked
+            | &BinOp::Offset => {
+                lhs_ty // lhs_ty can be != rhs_ty
+            }
+            &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
+                tcx.types.bool
+            }
+            &BinOp::Cmp => {
+                // these should be integer-like types of the same size.
+                assert_eq!(lhs_ty, rhs_ty);
+                tcx.ty_ordering_enum(None)
+            }
+        }
+    }
+    pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
+        match self {
+            // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
+            // on whether overflow checks are enabled or not.
+            BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
+            BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
+            BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
+            BinOp::Div => hir::BinOpKind::Div,
+            BinOp::Rem => hir::BinOpKind::Rem,
+            BinOp::BitXor => hir::BinOpKind::BitXor,
+            BinOp::BitAnd => hir::BinOpKind::BitAnd,
+            BinOp::BitOr => hir::BinOpKind::BitOr,
+            BinOp::Shl => hir::BinOpKind::Shl,
+            BinOp::Shr => hir::BinOpKind::Shr,
+            BinOp::Eq => hir::BinOpKind::Eq,
+            BinOp::Ne => hir::BinOpKind::Ne,
+            BinOp::Lt => hir::BinOpKind::Lt,
+            BinOp::Gt => hir::BinOpKind::Gt,
+            BinOp::Le => hir::BinOpKind::Le,
+            BinOp::Ge => hir::BinOpKind::Ge,
+            // We don't have HIR syntax for these.
+            BinOp::Cmp
+            | BinOp::AddUnchecked
+            | BinOp::SubUnchecked
+            | BinOp::MulUnchecked
+            | BinOp::ShlUnchecked
+            | BinOp::ShrUnchecked
+            | BinOp::Offset => {
+                unreachable!()
+            }
+        }
+    }
+
+    /// If this is a `FooWithOverflow`, return `Some(Foo)`.
+    pub fn overflowing_to_wrapping(self) -> Option<BinOp> {
+        Some(match self {
+            BinOp::AddWithOverflow => BinOp::Add,
+            BinOp::SubWithOverflow => BinOp::Sub,
+            BinOp::MulWithOverflow => BinOp::Mul,
+            _ => return None,
+        })
+    }
+
+    /// Returns whether this is a `FooWithOverflow`
+    pub fn is_overflowing(self) -> bool {
+        self.overflowing_to_wrapping().is_some()
+    }
+
+    /// If this is a `Foo`, return `Some(FooWithOverflow)`.
+    pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
+        Some(match self {
+            BinOp::Add => BinOp::AddWithOverflow,
+            BinOp::Sub => BinOp::SubWithOverflow,
+            BinOp::Mul => BinOp::MulWithOverflow,
+            _ => return None,
+        })
+    }
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index dfd40a9535b..389792a04f8 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1133,7 +1133,7 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 ///
 ///  1. The address in memory that the place refers to.
 ///  2. The provenance with which the place is being accessed.
-///  3. The type of the place and an optional variant index. See [`PlaceTy`][super::tcx::PlaceTy].
+///  3. The type of the place and an optional variant index. See [`PlaceTy`][super::PlaceTy].
 ///  4. Optionally, some metadata. This exists if and only if the type of the place is not `Sized`.
 ///
 /// We'll give a description below of how all pieces of the place except for the provenance are
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
deleted file mode 100644
index 862f78d7259..00000000000
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ /dev/null
@@ -1,416 +0,0 @@
-/*!
- * Methods for the various MIR types. These are intended for use after
- * building is complete.
- */
-
-use rustc_hir as hir;
-use tracing::{debug, instrument};
-use ty::CoroutineArgsExt;
-
-use crate::mir::*;
-
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct PlaceTy<'tcx> {
-    pub ty: Ty<'tcx>,
-    /// Downcast to a particular variant of an enum or a coroutine, if included.
-    pub variant_index: Option<VariantIdx>,
-}
-
-// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
-#[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16);
-
-impl<'tcx> PlaceTy<'tcx> {
-    #[inline]
-    pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
-        PlaceTy { ty, variant_index: None }
-    }
-
-    /// `place_ty.field_ty(tcx, f)` computes the type of a given field.
-    ///
-    /// Most clients of `PlaceTy` can instead just extract the relevant type
-    /// directly from their `PlaceElem`, but some instances of `ProjectionElem<V, T>`
-    /// do not carry a `Ty` for `T`.
-    ///
-    /// Note that the resulting type has not been normalized.
-    #[instrument(level = "debug", skip(tcx), ret)]
-    pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
-        if let Some(variant_index) = self.variant_index {
-            match *self.ty.kind() {
-                ty::Adt(adt_def, args) if adt_def.is_enum() => {
-                    adt_def.variant(variant_index).fields[f].ty(tcx, args)
-                }
-                ty::Coroutine(def_id, args) => {
-                    let mut variants = args.as_coroutine().state_tys(def_id, tcx);
-                    let Some(mut variant) = variants.nth(variant_index.into()) else {
-                        bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
-                    };
-
-                    variant
-                        .nth(f.index())
-                        .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
-                }
-                _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
-            }
-        } else {
-            match self.ty.kind() {
-                ty::Adt(adt_def, args) if !adt_def.is_enum() => {
-                    adt_def.non_enum_variant().fields[f].ty(tcx, args)
-                }
-                ty::Closure(_, args) => args
-                    .as_closure()
-                    .upvar_tys()
-                    .get(f.index())
-                    .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                ty::CoroutineClosure(_, args) => args
-                    .as_coroutine_closure()
-                    .upvar_tys()
-                    .get(f.index())
-                    .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                // Only prefix fields (upvars and current state) are
-                // accessible without a variant index.
-                ty::Coroutine(_, args) => args
-                    .as_coroutine()
-                    .prefix_tys()
-                    .get(f.index())
-                    .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                ty::Tuple(tys) => tys
-                    .get(f.index())
-                    .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                _ => bug!("can't project out of {self:?}"),
-            }
-        }
-    }
-
-    pub fn multi_projection_ty(
-        self,
-        tcx: TyCtxt<'tcx>,
-        elems: &[PlaceElem<'tcx>],
-    ) -> PlaceTy<'tcx> {
-        elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
-    }
-
-    /// Convenience wrapper around `projection_ty_core` for
-    /// `PlaceElem`, where we can just use the `Ty` that is already
-    /// stored inline on field projection elems.
-    pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
-        self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
-    }
-
-    /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
-    /// projects `place_ty` onto `elem`, returning the appropriate
-    /// `Ty` or downcast variant corresponding to that projection.
-    /// The `handle_field` callback must map a `FieldIdx` to its `Ty`,
-    /// (which should be trivial when `T` = `Ty`).
-    pub fn projection_ty_core<V, T>(
-        self,
-        tcx: TyCtxt<'tcx>,
-        elem: &ProjectionElem<V, T>,
-        mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
-        mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
-    ) -> PlaceTy<'tcx>
-    where
-        V: ::std::fmt::Debug,
-        T: ::std::fmt::Debug + Copy,
-    {
-        if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
-            bug!("cannot use non field projection on downcasted place")
-        }
-        let answer = match *elem {
-            ProjectionElem::Deref => {
-                let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
-                    bug!("deref projection of non-dereferenceable ty {:?}", self)
-                });
-                PlaceTy::from_ty(ty)
-            }
-            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
-                PlaceTy::from_ty(self.ty.builtin_index().unwrap())
-            }
-            ProjectionElem::Subslice { from, to, from_end } => {
-                PlaceTy::from_ty(match self.ty.kind() {
-                    ty::Slice(..) => self.ty,
-                    ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
-                    ty::Array(inner, size) if from_end => {
-                        let size = size
-                            .try_to_target_usize(tcx)
-                            .expect("expected subslice projection on fixed-size array");
-                        let len = size - from - to;
-                        Ty::new_array(tcx, *inner, len)
-                    }
-                    _ => bug!("cannot subslice non-array type: `{:?}`", self),
-                })
-            }
-            ProjectionElem::Downcast(_name, index) => {
-                PlaceTy { ty: self.ty, variant_index: Some(index) }
-            }
-            ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
-            ProjectionElem::OpaqueCast(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
-            }
-            ProjectionElem::Subtype(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
-            }
-
-            // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
-            ProjectionElem::UnwrapUnsafeBinder(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
-            }
-        };
-        debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
-        answer
-    }
-}
-
-impl<'tcx> Place<'tcx> {
-    pub fn ty_from<D: ?Sized>(
-        local: Local,
-        projection: &[PlaceElem<'tcx>],
-        local_decls: &D,
-        tcx: TyCtxt<'tcx>,
-    ) -> PlaceTy<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection)
-    }
-
-    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        Place::ty_from(self.local, self.projection, local_decls, tcx)
-    }
-}
-
-impl<'tcx> PlaceRef<'tcx> {
-    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        Place::ty_from(self.local, self.projection, local_decls, tcx)
-    }
-}
-
-pub enum RvalueInitializationState {
-    Shallow,
-    Deep,
-}
-
-impl<'tcx> Rvalue<'tcx> {
-    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        match *self {
-            Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
-            Rvalue::Repeat(ref operand, count) => {
-                Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count)
-            }
-            Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
-            Rvalue::Ref(reg, bk, ref place) => {
-                let place_ty = place.ty(local_decls, tcx).ty;
-                Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
-            }
-            Rvalue::RawPtr(kind, ref place) => {
-                let place_ty = place.ty(local_decls, tcx).ty;
-                Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
-            }
-            Rvalue::Len(..) => tcx.types.usize,
-            Rvalue::Cast(.., ty) => ty,
-            Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
-                let lhs_ty = lhs.ty(local_decls, tcx);
-                let rhs_ty = rhs.ty(local_decls, tcx);
-                op.ty(tcx, lhs_ty, rhs_ty)
-            }
-            Rvalue::UnaryOp(op, ref operand) => {
-                let arg_ty = operand.ty(local_decls, tcx);
-                op.ty(tcx, arg_ty)
-            }
-            Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
-            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
-                tcx.types.usize
-            }
-            Rvalue::NullaryOp(NullOp::ContractChecks, _)
-            | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
-            Rvalue::Aggregate(ref ak, ref ops) => match **ak {
-                AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
-                AggregateKind::Tuple => {
-                    Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
-                }
-                AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
-                AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
-                AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args),
-                AggregateKind::CoroutineClosure(did, args) => {
-                    Ty::new_coroutine_closure(tcx, did, args)
-                }
-                AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability),
-            },
-            Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
-            Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,
-            Rvalue::WrapUnsafeBinder(_, ty) => ty,
-        }
-    }
-
-    #[inline]
-    /// Returns `true` if this rvalue is deeply initialized (most rvalues) or
-    /// whether its only shallowly initialized (`Rvalue::Box`).
-    pub fn initialization_state(&self) -> RvalueInitializationState {
-        match *self {
-            Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow,
-            _ => RvalueInitializationState::Deep,
-        }
-    }
-}
-
-impl<'tcx> Operand<'tcx> {
-    pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        match self {
-            &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
-            Operand::Constant(c) => c.const_.ty(),
-        }
-    }
-
-    pub fn span<D: ?Sized>(&self, local_decls: &D) -> Span
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        match self {
-            &Operand::Copy(ref l) | &Operand::Move(ref l) => {
-                local_decls.local_decls()[l.local].source_info.span
-            }
-            Operand::Constant(c) => c.span,
-        }
-    }
-}
-
-impl<'tcx> BinOp {
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> {
-        // FIXME: handle SIMD correctly
-        match self {
-            &BinOp::Add
-            | &BinOp::AddUnchecked
-            | &BinOp::Sub
-            | &BinOp::SubUnchecked
-            | &BinOp::Mul
-            | &BinOp::MulUnchecked
-            | &BinOp::Div
-            | &BinOp::Rem
-            | &BinOp::BitXor
-            | &BinOp::BitAnd
-            | &BinOp::BitOr => {
-                // these should be integers or floats of the same size.
-                assert_eq!(lhs_ty, rhs_ty);
-                lhs_ty
-            }
-            &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
-                // these should be integers of the same size.
-                assert_eq!(lhs_ty, rhs_ty);
-                Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
-            }
-            &BinOp::Shl
-            | &BinOp::ShlUnchecked
-            | &BinOp::Shr
-            | &BinOp::ShrUnchecked
-            | &BinOp::Offset => {
-                lhs_ty // lhs_ty can be != rhs_ty
-            }
-            &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
-                tcx.types.bool
-            }
-            &BinOp::Cmp => {
-                // these should be integer-like types of the same size.
-                assert_eq!(lhs_ty, rhs_ty);
-                tcx.ty_ordering_enum(None)
-            }
-        }
-    }
-}
-
-impl<'tcx> UnOp {
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
-        match self {
-            UnOp::Not | UnOp::Neg => arg_ty,
-            UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
-        }
-    }
-}
-
-impl BorrowKind {
-    pub fn to_mutbl_lossy(self) -> hir::Mutability {
-        match self {
-            BorrowKind::Mut { .. } => hir::Mutability::Mut,
-            BorrowKind::Shared => hir::Mutability::Not,
-
-            // We have no type corresponding to a shallow borrow, so use
-            // `&` as an approximation.
-            BorrowKind::Fake(_) => hir::Mutability::Not,
-        }
-    }
-}
-
-impl BinOp {
-    pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
-        match self {
-            // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
-            // on whether overflow checks are enabled or not.
-            BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
-            BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
-            BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
-            BinOp::Div => hir::BinOpKind::Div,
-            BinOp::Rem => hir::BinOpKind::Rem,
-            BinOp::BitXor => hir::BinOpKind::BitXor,
-            BinOp::BitAnd => hir::BinOpKind::BitAnd,
-            BinOp::BitOr => hir::BinOpKind::BitOr,
-            BinOp::Shl => hir::BinOpKind::Shl,
-            BinOp::Shr => hir::BinOpKind::Shr,
-            BinOp::Eq => hir::BinOpKind::Eq,
-            BinOp::Ne => hir::BinOpKind::Ne,
-            BinOp::Lt => hir::BinOpKind::Lt,
-            BinOp::Gt => hir::BinOpKind::Gt,
-            BinOp::Le => hir::BinOpKind::Le,
-            BinOp::Ge => hir::BinOpKind::Ge,
-            // We don't have HIR syntax for these.
-            BinOp::Cmp
-            | BinOp::AddUnchecked
-            | BinOp::SubUnchecked
-            | BinOp::MulUnchecked
-            | BinOp::ShlUnchecked
-            | BinOp::ShrUnchecked
-            | BinOp::Offset => {
-                unreachable!()
-            }
-        }
-    }
-
-    /// If this is a `FooWithOverflow`, return `Some(Foo)`.
-    pub fn overflowing_to_wrapping(self) -> Option<BinOp> {
-        Some(match self {
-            BinOp::AddWithOverflow => BinOp::Add,
-            BinOp::SubWithOverflow => BinOp::Sub,
-            BinOp::MulWithOverflow => BinOp::Mul,
-            _ => return None,
-        })
-    }
-
-    /// Returns whether this is a `FooWithOverflow`
-    pub fn is_overflowing(self) -> bool {
-        self.overflowing_to_wrapping().is_some()
-    }
-
-    /// If this is a `Foo`, return `Some(FooWithOverflow)`.
-    pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
-        Some(match self {
-            BinOp::Add => BinOp::AddWithOverflow,
-            BinOp::Sub => BinOp::SubWithOverflow,
-            BinOp::Mul => BinOp::MulWithOverflow,
-            _ => return None,
-        })
-    }
-}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 8ad88fbda7c..98e8f269c57 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -270,10 +270,12 @@ macro_rules! make_mir_visitor {
 
             fn visit_local(
                 &mut self,
-                _local: $(& $mutability)? Local,
-                _context: PlaceContext,
-                _location: Location,
-            ) {}
+                local: $(& $mutability)? Local,
+                context: PlaceContext,
+                location: Location,
+            ) {
+                self.super_local(local, context, location)
+            }
 
             fn visit_source_scope(
                 &mut self,
@@ -292,9 +294,11 @@ macro_rules! make_mir_visitor {
                 super_body!(self, body, $($mutability, true)?);
             }
 
-            fn super_basic_block_data(&mut self,
-                                      block: BasicBlock,
-                                      data: & $($mutability)? BasicBlockData<'tcx>) {
+            fn super_basic_block_data(
+                &mut self,
+                block: BasicBlock,
+                data: & $($mutability)? BasicBlockData<'tcx>)
+            {
                 let BasicBlockData {
                     statements,
                     terminator,
@@ -339,24 +343,24 @@ macro_rules! make_mir_visitor {
                     match callee_def {
                         ty::InstanceKind::Item(_def_id) => {}
 
-                        ty::InstanceKind::Intrinsic(_def_id) |
-                        ty::InstanceKind::VTableShim(_def_id) |
-                        ty::InstanceKind::ReifyShim(_def_id, _) |
-                        ty::InstanceKind::Virtual(_def_id, _) |
-                        ty::InstanceKind::ThreadLocalShim(_def_id) |
-                        ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
-                        ty::InstanceKind::ConstructCoroutineInClosureShim {
+                        ty::InstanceKind::Intrinsic(_def_id)
+                        | ty::InstanceKind::VTableShim(_def_id)
+                        | ty::InstanceKind::ReifyShim(_def_id, _)
+                        | ty::InstanceKind::Virtual(_def_id, _)
+                        | ty::InstanceKind::ThreadLocalShim(_def_id)
+                        | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ }
+                        | ty::InstanceKind::ConstructCoroutineInClosureShim {
                             coroutine_closure_def_id: _def_id,
                             receiver_by_ref: _,
-                        } |
-                        ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) |
-                        ty::InstanceKind::DropGlue(_def_id, None) => {}
-
-                        ty::InstanceKind::FnPtrShim(_def_id, ty) |
-                        ty::InstanceKind::DropGlue(_def_id, Some(ty)) |
-                        ty::InstanceKind::CloneShim(_def_id, ty) |
-                        ty::InstanceKind::FnPtrAddrShim(_def_id, ty) |
-                        ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
+                        }
+                        | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None)
+                        | ty::InstanceKind::DropGlue(_def_id, None) => {}
+
+                        ty::InstanceKind::FnPtrShim(_def_id, ty)
+                        | ty::InstanceKind::DropGlue(_def_id, Some(ty))
+                        | ty::InstanceKind::CloneShim(_def_id, ty)
+                        | ty::InstanceKind::FnPtrAddrShim(_def_id, ty)
+                        | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
                             // FIXME(eddyb) use a better `TyContext` here.
                             self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                         }
@@ -368,19 +372,16 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_statement(&mut self,
-                               statement: & $($mutability)? Statement<'tcx>,
-                               location: Location) {
-                let Statement {
-                    source_info,
-                    kind,
-                } = statement;
+            fn super_statement(
+                &mut self,
+                statement: & $($mutability)? Statement<'tcx>,
+                location: Location
+            ) {
+                let Statement { source_info, kind } = statement;
 
                 self.visit_source_info(source_info);
                 match kind {
-                    StatementKind::Assign(
-                        box (place, rvalue)
-                    ) => {
+                    StatementKind::Assign(box (place, rvalue)) => {
                         self.visit_assign(place, rvalue, location);
                     }
                     StatementKind::FakeRead(box (_, place)) => {
@@ -428,11 +429,13 @@ macro_rules! make_mir_visitor {
                             location
                         );
                     }
-                    StatementKind::AscribeUserType(
-                        box (place, user_ty),
-                        variance
-                    ) => {
-                        self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location);
+                    StatementKind::AscribeUserType(box (place, user_ty), variance) => {
+                        self.visit_ascribe_user_ty(
+                            place,
+                            $(& $mutability)? *variance,
+                            user_ty,
+                            location
+                        );
                     }
                     StatementKind::Coverage(coverage) => {
                         self.visit_coverage(
@@ -443,7 +446,11 @@ macro_rules! make_mir_visitor {
                     StatementKind::Intrinsic(box ref $($mutability)? intrinsic) => {
                         match intrinsic {
                             NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
-                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
+                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                                src,
+                                dst,
+                                count
+                            }) => {
                                 self.visit_operand(src, location);
                                 self.visit_operand(dst, location);
                                 self.visit_operand(count, location);
@@ -456,10 +463,12 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_assign(&mut self,
-                            place: &$($mutability)? Place<'tcx>,
-                            rvalue: &$($mutability)? Rvalue<'tcx>,
-                            location: Location) {
+            fn super_assign(
+                &mut self,
+                place: &$($mutability)? Place<'tcx>,
+                rvalue: &$($mutability)? Rvalue<'tcx>,
+                location: Location
+            ) {
                 self.visit_place(
                     place,
                     PlaceContext::MutatingUse(MutatingUseContext::Store),
@@ -468,20 +477,22 @@ macro_rules! make_mir_visitor {
                 self.visit_rvalue(rvalue, location);
             }
 
-            fn super_terminator(&mut self,
-                                terminator: &$($mutability)? Terminator<'tcx>,
-                                location: Location) {
+            fn super_terminator(
+                &mut self,
+                terminator: &$($mutability)? Terminator<'tcx>,
+                location: Location
+            ) {
                 let Terminator { source_info, kind } = terminator;
 
                 self.visit_source_info(source_info);
                 match kind {
-                    TerminatorKind::Goto { .. } |
-                    TerminatorKind::UnwindResume |
-                    TerminatorKind::UnwindTerminate(_) |
-                    TerminatorKind::CoroutineDrop |
-                    TerminatorKind::Unreachable |
-                    TerminatorKind::FalseEdge { .. } |
-                    TerminatorKind::FalseUnwind { .. } => {}
+                    TerminatorKind::Goto { .. }
+                    | TerminatorKind::UnwindResume
+                    | TerminatorKind::UnwindTerminate(_)
+                    | TerminatorKind::CoroutineDrop
+                    | TerminatorKind::Unreachable
+                    | TerminatorKind::FalseEdge { .. }
+                    | TerminatorKind::FalseUnwind { .. } => {}
 
                     TerminatorKind::Return => {
                         // `return` logically moves from the return place `_0`. Note that the place
@@ -500,19 +511,11 @@ macro_rules! make_mir_visitor {
                         );
                     }
 
-                    TerminatorKind::SwitchInt {
-                        discr,
-                        targets: _
-                    } => {
+                    TerminatorKind::SwitchInt { discr, targets: _ } => {
                         self.visit_operand(discr, location);
                     }
 
-                    TerminatorKind::Drop {
-                        place,
-                        target: _,
-                        unwind: _,
-                        replace: _,
-                    } => {
+                    TerminatorKind::Drop { place, target: _, unwind: _, replace: _ } => {
                         self.visit_place(
                             place,
                             PlaceContext::MutatingUse(MutatingUseContext::Drop),
@@ -541,11 +544,7 @@ macro_rules! make_mir_visitor {
                         );
                     }
 
-                    TerminatorKind::TailCall {
-                        func,
-                        args,
-                        fn_span,
-                    } => {
+                    TerminatorKind::TailCall { func, args, fn_span } => {
                         self.visit_span($(& $mutability)? *fn_span);
                         self.visit_operand(func, location);
                         for arg in args {
@@ -553,23 +552,12 @@ macro_rules! make_mir_visitor {
                         }
                     },
 
-                    TerminatorKind::Assert {
-                        cond,
-                        expected: _,
-                        msg,
-                        target: _,
-                        unwind: _,
-                    } => {
+                    TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                         self.visit_operand(cond, location);
                         self.visit_assert_message(msg, location);
                     }
 
-                    TerminatorKind::Yield {
-                        value,
-                        resume: _,
-                        resume_arg,
-                        drop: _,
-                    } => {
+                    TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
                         self.visit_operand(value, location);
                         self.visit_place(
                             resume_arg,
@@ -622,9 +610,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_assert_message(&mut self,
-                                    msg: & $($mutability)? AssertMessage<'tcx>,
-                                    location: Location) {
+            fn super_assert_message(
+                &mut self,
+                msg: & $($mutability)? AssertMessage<'tcx>,
+                location: Location
+            ) {
                 use crate::mir::AssertKind::*;
                 match msg {
                     BoundsCheck { len, index } => {
@@ -648,9 +638,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_rvalue(&mut self,
-                            rvalue: & $($mutability)? Rvalue<'tcx>,
-                            location: Location) {
+            fn super_rvalue(
+                &mut self,
+                rvalue: & $($mutability)? Rvalue<'tcx>,
+                location: Location
+            ) {
                 match rvalue {
                     Rvalue::Use(operand) => {
                         self.visit_operand(operand, location);
@@ -677,6 +669,7 @@ macro_rules! make_mir_visitor {
                         };
                         self.visit_place(path, ctx, location);
                     }
+
                     Rvalue::CopyForDeref(place) => {
                         self.visit_place(
                             place,
@@ -740,8 +733,7 @@ macro_rules! make_mir_visitor {
                             AggregateKind::Array(ty) => {
                                 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                             }
-                            AggregateKind::Tuple => {
-                            }
+                            AggregateKind::Tuple => {}
                             AggregateKind::Adt(
                                 _adt_def,
                                 _variant_index,
@@ -751,22 +743,13 @@ macro_rules! make_mir_visitor {
                             ) => {
                                 self.visit_args(args, location);
                             }
-                            AggregateKind::Closure(
-                                _,
-                                closure_args
-                            ) => {
+                            AggregateKind::Closure(_, closure_args) => {
                                 self.visit_args(closure_args, location);
                             }
-                            AggregateKind::Coroutine(
-                                _,
-                                coroutine_args,
-                            ) => {
+                            AggregateKind::Coroutine(_, coroutine_args) => {
                                 self.visit_args(coroutine_args, location);
                             }
-                            AggregateKind::CoroutineClosure(
-                                _,
-                                coroutine_closure_args,
-                            ) => {
+                            AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
                                 self.visit_args(coroutine_closure_args, location);
                             }
                             AggregateKind::RawPtr(ty, _) => {
@@ -791,9 +774,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_operand(&mut self,
-                             operand: & $($mutability)? Operand<'tcx>,
-                             location: Location) {
+            fn super_operand(
+                &mut self,
+                operand: & $($mutability)? Operand<'tcx>,
+                location: Location
+            ) {
                 match operand {
                     Operand::Copy(place) => {
                         self.visit_place(
@@ -815,28 +800,36 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_ascribe_user_ty(&mut self,
-                                     place: & $($mutability)? Place<'tcx>,
-                                     variance: $(& $mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection,
-                                     location: Location) {
+            fn super_ascribe_user_ty(
+                &mut self,
+                place: & $($mutability)? Place<'tcx>,
+                variance: $(& $mutability)? ty::Variance,
+                user_ty: & $($mutability)? UserTypeProjection,
+                location: Location)
+            {
                 self.visit_place(
                     place,
-                    PlaceContext::NonUse(NonUseContext::AscribeUserTy($(* &$mutability *)? variance)),
+                    PlaceContext::NonUse(
+                        NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
+                    ),
                     location
                 );
                 self.visit_user_type_projection(user_ty);
             }
 
-            fn super_coverage(&mut self,
-                              _kind: & $($mutability)? coverage::CoverageKind,
-                              _location: Location) {
+            fn super_coverage(
+                &mut self,
+                _kind: & $($mutability)? coverage::CoverageKind,
+                _location: Location
+            ) {
             }
 
-            fn super_retag(&mut self,
-                           _kind: $(& $mutability)? RetagKind,
-                           place: & $($mutability)? Place<'tcx>,
-                           location: Location) {
+            fn super_retag(
+                &mut self,
+                _kind: $(& $mutability)? RetagKind,
+                place: & $($mutability)? Place<'tcx>,
+                location: Location
+            ) {
                 self.visit_place(
                     place,
                     PlaceContext::MutatingUse(MutatingUseContext::Retag),
@@ -844,9 +837,11 @@ macro_rules! make_mir_visitor {
                 );
             }
 
-            fn super_local_decl(&mut self,
-                                local: Local,
-                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
+            fn super_local_decl(
+                &mut self,
+                local: Local,
+                local_decl: & $($mutability)? LocalDecl<'tcx>
+            ) {
                 let LocalDecl {
                     mutability: _,
                     ty,
@@ -862,12 +857,20 @@ macro_rules! make_mir_visitor {
                     source_info: *source_info,
                 });
                 if let Some(user_ty) = user_ty {
-                    for (user_ty, _) in & $($mutability)? user_ty.contents {
+                    for user_ty in & $($mutability)? user_ty.contents {
                         self.visit_user_type_projection(user_ty);
                     }
                 }
             }
 
+            fn super_local(
+                &mut self,
+                _local: $(& $mutability)? Local,
+                _context: PlaceContext,
+                _location: Location,
+            ) {
+            }
+
             fn super_var_debug_info(
                 &mut self,
                 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
@@ -882,7 +885,10 @@ macro_rules! make_mir_visitor {
 
                 self.visit_source_info(source_info);
                 let location = Location::START;
-                if let Some(box VarDebugInfoFragment { ref $($mutability)? ty, ref $($mutability)? projection }) = composite {
+                if let Some(box VarDebugInfoFragment {
+                    ref $($mutability)? ty,
+                    ref $($mutability)? projection
+                }) = composite {
                     self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                     for elem in projection {
                         let ProjectionElem::Field(_, ty) = elem else { bug!() };
@@ -900,10 +906,7 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_source_scope(
-                &mut self,
-                _scope: $(& $mutability)? SourceScope
-            ) {}
+            fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
 
             fn super_const_operand(
                 &mut self,
@@ -919,8 +922,12 @@ macro_rules! make_mir_visitor {
                 self.visit_span($(& $mutability)? *span);
                 match const_ {
                     Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
-                    Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
-                    Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
+                    Const::Val(_, ty) => {
+                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
+                    }
+                    Const::Unevaluated(_, ty) => {
+                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
+                    }
                 }
             }
 
@@ -929,27 +936,18 @@ macro_rules! make_mir_visitor {
                 _ct: $(& $mutability)? ty::Const<'tcx>,
                 _location: Location,
             ) {
-
             }
 
-            fn super_span(&mut self, _span: $(& $mutability)? Span) {
-            }
+            fn super_span(&mut self, _span: $(& $mutability)? Span) {}
 
             fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
-                let SourceInfo {
-                    span,
-                    scope,
-                } = source_info;
+                let SourceInfo { span, scope } = source_info;
 
                 self.visit_span($(& $mutability)? *span);
                 self.visit_source_scope($(& $mutability)? *scope);
             }
 
-            fn super_user_type_projection(
-                &mut self,
-                _ty: & $($mutability)? UserTypeProjection,
-            ) {
-            }
+            fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
 
             fn super_user_type_annotation(
                 &mut self,
@@ -960,14 +958,11 @@ macro_rules! make_mir_visitor {
                 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
             }
 
-            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
-            }
+            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
 
-            fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
-            }
+            fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
 
-            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {
-            }
+            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
 
             // Convenience methods
 
@@ -976,7 +971,8 @@ macro_rules! make_mir_visitor {
                 body: &$($mutability)? Body<'tcx>,
                 location: Location
             ) {
-                let basic_block = & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
+                let basic_block =
+                    & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
                 if basic_block.statements.len() == location.statement_index {
                     if let Some(ref $($mutability)? terminator) = basic_block.terminator {
                         self.visit_terminator(terminator, location)
@@ -1255,28 +1251,6 @@ macro_rules! visit_place_fns {
 make_mir_visitor!(Visitor,);
 make_mir_visitor!(MutVisitor, mut);
 
-pub trait MirVisitable<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
-}
-
-impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_statement(self, location)
-    }
-}
-
-impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_terminator(self, location)
-    }
-}
-
-impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_terminator(self.as_ref().unwrap(), location)
-    }
-}
-
 /// Extra information passed to `visit_ty` and friends to give context
 /// about where the type etc appears.
 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 693823b4af4..7c4ea06a746 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -802,7 +802,7 @@ rustc_queries! {
 
     query adt_dtorck_constraint(
         key: DefId
-    ) -> Result<&'tcx DropckConstraint<'tcx>, NoSolution> {
+    ) -> &'tcx DropckConstraint<'tcx> {
         desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
     }
 
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 2ab8750f727..98cc00c367c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -376,7 +376,6 @@ pub enum ExprKind<'tcx> {
     /// A `match` expression.
     Match {
         scrutinee: ExprId,
-        scrutinee_hir_id: HirId,
         arms: Box<[ArmId]>,
         match_source: MatchSource,
     },
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index f659bf8125a..9c74f6263b3 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -1,9 +1,9 @@
-use rustc_ast_ir::try_visit;
 use rustc_data_structures::intern::Interned;
 use rustc_macros::HashStable;
 use rustc_type_ir as ir;
 pub use rustc_type_ir::solve::*;
 
+use crate::ty::visit::try_visit;
 use crate::ty::{
     self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
 };
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 56a38a84c9f..b74ddb81710 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -6,8 +6,6 @@ use std::mem;
 use std::num::NonZero;
 use std::ptr::NonNull;
 
-use rustc_ast_ir::visit::VisitorResult;
-use rustc_ast_ir::walk_visitable_list;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
@@ -18,7 +16,7 @@ use smallvec::SmallVec;
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitor, VisitorResult, walk_visitable_list};
 use crate::ty::{
     self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt,
 };
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index bbb8a9fa671..eb14ed20fba 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -229,11 +229,32 @@ impl fmt::Display for ValidityRequirement {
 
 #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
 pub enum LayoutError<'tcx> {
+    /// A type doesn't have a sensible layout.
+    ///
+    /// This variant is used for layout errors that don't necessarily cause
+    /// compile errors.
+    ///
+    /// For example, this can happen if a struct contains an unsized type in a
+    /// non-tail field, but has an unsatisfiable bound like `str: Sized`.
     Unknown(Ty<'tcx>),
+    /// The size of a type exceeds [`TargetDataLayout::obj_size_bound`].
     SizeOverflow(Ty<'tcx>),
+    /// The layout can vary due to a generic parameter.
+    ///
+    /// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout
+    /// may become computable after further instantiating the generic parameter(s).
     TooGeneric(Ty<'tcx>),
+    /// An alias failed to normalize.
+    ///
+    /// This variant is necessary, because, due to trait solver incompleteness, it is
+    /// possible than an alias that was rigid during analysis fails to normalize after
+    /// revealing opaque types.
+    ///
+    /// See `tests/ui/layout/normalization-failure.rs` for an example.
     NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
+    /// A non-layout error is reported elsewhere.
     ReferencesError(ErrorGuaranteed),
+    /// A type has cyclic layout, i.e. the type contains itself without indirection.
     Cycle(ErrorGuaranteed),
 }
 
@@ -243,11 +264,11 @@ impl<'tcx> LayoutError<'tcx> {
 
         use crate::fluent_generated::*;
         match self {
-            Unknown(_) => middle_unknown_layout,
-            SizeOverflow(_) => middle_values_too_big,
-            TooGeneric(_) => middle_too_generic,
-            NormalizationFailure(_, _) => middle_cannot_be_normalized,
-            Cycle(_) => middle_cycle,
+            Unknown(_) => middle_layout_unknown,
+            SizeOverflow(_) => middle_layout_size_overflow,
+            TooGeneric(_) => middle_layout_too_generic,
+            NormalizationFailure(_, _) => middle_layout_normalization_failure,
+            Cycle(_) => middle_layout_cycle,
             ReferencesError(_) => middle_layout_references_error,
         }
     }
@@ -276,7 +297,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
         match *self {
             LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
             LayoutError::TooGeneric(ty) => {
-                write!(f, "`{ty}` does not have a fixed size")
+                write!(f, "the type `{ty}` does not have a fixed layout")
             }
             LayoutError::SizeOverflow(ty) => {
                 write!(f, "values of the type `{ty}` are too big for the target architecture")
@@ -773,8 +794,9 @@ where
                         Some(fields) => FieldsShape::Union(fields),
                         None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
                     },
-                    backend_repr: BackendRepr::Uninhabited,
+                    backend_repr: BackendRepr::Memory { sized: true },
                     largest_niche: None,
+                    uninhabited: true,
                     align: tcx.data_layout.i8_align,
                     size: Size::ZERO,
                     max_repr_align: None,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c52e774c8b7..a1d44882e63 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -27,7 +27,6 @@ pub use intrinsic::IntrinsicDef;
 use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::node_id::NodeMap;
-pub use rustc_ast_ir::{Movability, Mutability, try_visit};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -48,7 +47,7 @@ pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym};
 pub use rustc_type_ir::relate::VarianceDiagInfo;
-pub use rustc_type_ir::*;
+pub use rustc_type_ir::{Movability, Mutability, *};
 use tracing::{debug, instrument};
 pub use vtable::*;
 use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6c15e033bb0..b2286c74402 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -7,13 +7,12 @@ use std::fmt::{self, Debug};
 
 use rustc_abi::TyAndLayout;
 use rustc_ast::InlineAsmTemplatePiece;
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_type_ir::ConstKind;
+use rustc_type_ir::visit::{VisitorResult, try_visit};
 
 use super::print::PrettyPrinter;
 use super::{GenericArg, GenericArgKind, Pattern, Region};
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 4efaccefcf7..95256b55bb4 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -2,7 +2,7 @@ use std::ops::ControlFlow;
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_type_ir::fold::TypeFoldable;
-pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+pub use rustc_type_ir::visit::*;
 
 use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index eab414e150f..19669021eef 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -1,6 +1,5 @@
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty;
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index ed577f7adeb..6334612eced 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -926,12 +926,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Note that the variance doesn't apply here, as we are tracking the effect
                 // of `user_ty` on any bindings contained with subpattern.
 
-                let projection = UserTypeProjection {
-                    base: self.canonical_user_type_annotations.push(annotation.clone()),
-                    projs: Vec::new(),
-                };
-                let subpattern_user_ty =
-                    pattern_user_ty.push_projection(&projection, annotation.span);
+                let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone());
+                let subpattern_user_ty = pattern_user_ty.push_user_type(base_user_ty);
                 self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
             }
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 54da6924db4..d0fca76fcf0 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -828,7 +828,6 @@ impl<'tcx> ThirBuildCx<'tcx> {
             },
             hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match {
                 scrutinee: self.mirror_expr(discr),
-                scrutinee_hir_id: discr.hir_id,
                 arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
                 match_source,
             },
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 1e738801011..6dbb460d8b1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -151,7 +151,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
                 }
                 return;
             }
-            ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => {
+            ExprKind::Match { scrutinee, box ref arms, match_source } => {
                 self.check_match(scrutinee, arms, match_source, ex.span);
             }
             ExprKind::Let { box ref pat, expr } => {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index b6c259aa4e0..8bbc89fdcec 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -1,7 +1,6 @@
 use std::mem;
 
 use rustc_index::IndexVec;
-use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index a51af8c40fd..104a2e8c091 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index afc49c5cc54..f3f3a65cd80 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -393,12 +393,13 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
 
     fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
         // Remove StorageLive and StorageDead statements for remapped locals
-        data.retain_statements(|s| match s.kind {
-            StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
-                !self.remap.contains(l)
+        for s in &mut data.statements {
+            if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = s.kind
+                && self.remap.contains(l)
+            {
+                s.make_nop();
             }
-            _ => true,
-        });
+        }
 
         let ret_val = match data.terminator().kind {
             TerminatorKind::Return => {
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 264995efe8f..1ccae0fd7fe 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -346,35 +346,37 @@ fn extract_hole_spans_from_hir<'tcx>(
     body_span: Span, // Usually `hir_body.value.span`, but not always
     hir_body: &hir::Body<'tcx>,
 ) -> Vec<Span> {
-    struct HolesVisitor<'hir, F> {
-        tcx: TyCtxt<'hir>,
-        visit_hole_span: F,
+    struct HolesVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        body_span: Span,
+        hole_spans: Vec<Span>,
     }
 
-    impl<'hir, F: FnMut(Span)> Visitor<'hir> for HolesVisitor<'hir, F> {
-        /// - We need `NestedFilter::INTRA = true` so that `visit_item` will be called.
-        /// - Bodies of nested items don't actually get visited, because of the
-        ///   `visit_item` override.
-        /// - For nested bodies that are not part of an item, we do want to visit any
-        ///   items contained within them.
-        type NestedFilter = nested_filter::All;
+    impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> {
+        /// We have special handling for nested items, but we still want to
+        /// traverse into nested bodies of things that are not considered items,
+        /// such as "anon consts" (e.g. array lengths).
+        type NestedFilter = nested_filter::OnlyBodies;
 
-        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
             self.tcx
         }
 
-        fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
-            (self.visit_hole_span)(item.span);
+        /// We override `visit_nested_item` instead of `visit_item` because we
+        /// only need the item's span, not the item itself.
+        fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result {
+            let span = self.tcx.def_span(id.owner_id.def_id);
+            self.visit_hole_span(span);
             // Having visited this item, we don't care about its children,
             // so don't call `walk_item`.
         }
 
         // We override `visit_expr` instead of the more specific expression
         // visitors, so that we have direct access to the expression span.
-        fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
+        fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
             match expr.kind {
                 hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => {
-                    (self.visit_hole_span)(expr.span);
+                    self.visit_hole_span(expr.span);
                     // Having visited this expression, we don't care about its
                     // children, so don't call `walk_expr`.
                 }
@@ -384,18 +386,17 @@ fn extract_hole_spans_from_hir<'tcx>(
             }
         }
     }
-
-    let mut hole_spans = vec![];
-    let mut visitor = HolesVisitor {
-        tcx,
-        visit_hole_span: |hole_span| {
+    impl HolesVisitor<'_> {
+        fn visit_hole_span(&mut self, hole_span: Span) {
             // Discard any holes that aren't directly visible within the body span.
-            if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) {
-                hole_spans.push(hole_span);
+            if self.body_span.contains(hole_span) && self.body_span.eq_ctxt(hole_span) {
+                self.hole_spans.push(hole_span);
             }
-        },
-    };
+        }
+    }
+
+    let mut visitor = HolesVisitor { tcx, body_span, hole_spans: vec![] };
 
     visitor.visit_body(hir_body);
-    hole_spans
+    visitor.hole_spans
 }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 2de55e38052..0d8cf524661 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -185,7 +185,7 @@ where
             place.ty(self.elaborator.body(), self.tcx()).ty
         } else {
             // We don't have a slice with all the locals, since some are in the patch.
-            tcx::PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local))
+            PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local))
                 .multi_projection_ty(self.elaborator.tcx(), place.projection)
                 .ty
         }
@@ -266,8 +266,21 @@ where
                 let tcx = self.tcx();
 
                 assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
-                let field_ty =
-                    tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args));
+                // The type error for normalization may have been in dropck: see
+                // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have
+                // deleted the MIR body and could have an error here as well.
+                let field_ty = match tcx
+                    .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args))
+                {
+                    Ok(t) => t,
+                    Err(_) => Ty::new_error(
+                        self.tcx(),
+                        self.elaborator
+                            .body()
+                            .tainted_by_errors
+                            .expect("Error in drop elaboration not found by dropck."),
+                    ),
+                };
 
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index ab6aafab446..530c72ca549 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -417,7 +417,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                 ..
             } = data.terminator().kind
             {
-                assert!(!self.patch.is_patched(bb));
+                assert!(!self.patch.is_term_patched(bb));
 
                 let loc = Location { block: tgt, statement_index: 0 };
                 let path = self.move_data().rev_lookup.find(destination.as_ref());
@@ -462,7 +462,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                             // a Goto; see `MirPatch::new`).
                         }
                         _ => {
-                            assert!(!self.patch.is_patched(bb));
+                            assert!(!self.patch.is_term_patched(bb));
                         }
                     }
                 }
@@ -486,7 +486,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                 ..
             } = data.terminator().kind
             {
-                assert!(!self.patch.is_patched(bb));
+                assert!(!self.patch.is_term_patched(bb));
 
                 let loc = Location { block: bb, statement_index: data.statements.len() };
                 let path = self.move_data().rev_lookup.find(destination.as_ref());
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 77a3854ebde..2f8a3050199 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1558,8 +1558,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             return true;
         };
 
+        if layout.uninhabited {
+            return true;
+        }
+
         match layout.backend_repr {
-            BackendRepr::Uninhabited => true,
             BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx),
             BackendRepr::ScalarPair(a, b) => {
                 !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx)
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 1e546bfbeb3..47cb478fe33 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -6,6 +6,8 @@ use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_session::Session;
 
+use crate::patch::MirPatch;
+
 /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
 /// enough discrepancy between them.
 ///
@@ -41,31 +43,34 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
         let mut alloc_cache = FxHashMap::default();
         let typing_env = body.typing_env(tcx);
 
-        let blocks = body.basic_blocks.as_mut();
-        let local_decls = &mut body.local_decls;
+        let mut patch = MirPatch::new(body);
 
-        for bb in blocks {
-            bb.expand_statements(|st| {
+        for (block, data) in body.basic_blocks.as_mut().iter_enumerated_mut() {
+            for (statement_index, st) in data.statements.iter_mut().enumerate() {
                 let StatementKind::Assign(box (
                     lhs,
                     Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
                 )) = &st.kind
                 else {
-                    return None;
+                    continue;
                 };
 
-                let ty = lhs.ty(local_decls, tcx).ty;
+                let location = Location { block, statement_index };
 
-                let (adt_def, num_variants, alloc_id) =
-                    self.candidate(tcx, typing_env, ty, &mut alloc_cache)?;
+                let ty = lhs.ty(&body.local_decls, tcx).ty;
 
-                let source_info = st.source_info;
-                let span = source_info.span;
+                let Some((adt_def, num_variants, alloc_id)) =
+                    self.candidate(tcx, typing_env, ty, &mut alloc_cache)
+                else {
+                    continue;
+                };
+
+                let span = st.source_info.span;
 
                 let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
-                let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
-                let store_live =
-                    Statement { source_info, kind: StatementKind::StorageLive(size_array_local) };
+                let size_array_local = patch.new_temp(tmp_ty, span);
+
+                let store_live = StatementKind::StorageLive(size_array_local);
 
                 let place = Place::from(size_array_local);
                 let constant_vals = ConstOperand {
@@ -77,108 +82,63 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                     ),
                 };
                 let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals)));
-                let const_assign =
-                    Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) };
-
-                let discr_place = Place::from(
-                    local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)),
-                );
-                let store_discr = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        discr_place,
-                        Rvalue::Discriminant(*rhs),
-                    ))),
-                };
-
-                let discr_cast_place =
-                    Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
-                let cast_discr = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        discr_cast_place,
-                        Rvalue::Cast(
-                            CastKind::IntToInt,
-                            Operand::Copy(discr_place),
-                            tcx.types.usize,
-                        ),
-                    ))),
-                };
-
-                let size_place =
-                    Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
-                let store_size = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        size_place,
-                        Rvalue::Use(Operand::Copy(Place {
-                            local: size_array_local,
-                            projection: tcx
-                                .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
-                        })),
-                    ))),
-                };
-
-                let dst =
-                    Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)));
-                let dst_ptr = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        dst,
-                        Rvalue::RawPtr(RawPtrKind::Mut, *lhs),
-                    ))),
-                };
+                let const_assign = StatementKind::Assign(Box::new((place, rval)));
+
+                let discr_place =
+                    Place::from(patch.new_temp(adt_def.repr().discr_type().to_ty(tcx), span));
+                let store_discr =
+                    StatementKind::Assign(Box::new((discr_place, Rvalue::Discriminant(*rhs))));
+
+                let discr_cast_place = Place::from(patch.new_temp(tcx.types.usize, span));
+                let cast_discr = StatementKind::Assign(Box::new((
+                    discr_cast_place,
+                    Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_place), tcx.types.usize),
+                )));
+
+                let size_place = Place::from(patch.new_temp(tcx.types.usize, span));
+                let store_size = StatementKind::Assign(Box::new((
+                    size_place,
+                    Rvalue::Use(Operand::Copy(Place {
+                        local: size_array_local,
+                        projection: tcx.mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
+                    })),
+                )));
+
+                let dst = Place::from(patch.new_temp(Ty::new_mut_ptr(tcx, ty), span));
+                let dst_ptr =
+                    StatementKind::Assign(Box::new((dst, Rvalue::RawPtr(RawPtrKind::Mut, *lhs))));
 
                 let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8);
-                let dst_cast_place =
-                    Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span)));
-                let dst_cast = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        dst_cast_place,
-                        Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
-                    ))),
-                };
+                let dst_cast_place = Place::from(patch.new_temp(dst_cast_ty, span));
+                let dst_cast = StatementKind::Assign(Box::new((
+                    dst_cast_place,
+                    Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
+                )));
 
-                let src =
-                    Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)));
-                let src_ptr = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        src,
-                        Rvalue::RawPtr(RawPtrKind::Const, *rhs),
-                    ))),
-                };
+                let src = Place::from(patch.new_temp(Ty::new_imm_ptr(tcx, ty), span));
+                let src_ptr =
+                    StatementKind::Assign(Box::new((src, Rvalue::RawPtr(RawPtrKind::Const, *rhs))));
 
                 let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8);
-                let src_cast_place =
-                    Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span)));
-                let src_cast = Statement {
-                    source_info,
-                    kind: StatementKind::Assign(Box::new((
-                        src_cast_place,
-                        Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
-                    ))),
-                };
+                let src_cast_place = Place::from(patch.new_temp(src_cast_ty, span));
+                let src_cast = StatementKind::Assign(Box::new((
+                    src_cast_place,
+                    Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
+                )));
 
-                let deinit_old =
-                    Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) };
-
-                let copy_bytes = Statement {
-                    source_info,
-                    kind: StatementKind::Intrinsic(Box::new(
-                        NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
-                            src: Operand::Copy(src_cast_place),
-                            dst: Operand::Copy(dst_cast_place),
-                            count: Operand::Copy(size_place),
-                        }),
-                    )),
-                };
+                let deinit_old = StatementKind::Deinit(Box::new(dst));
+
+                let copy_bytes = StatementKind::Intrinsic(Box::new(
+                    NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                        src: Operand::Copy(src_cast_place),
+                        dst: Operand::Copy(dst_cast_place),
+                        count: Operand::Copy(size_place),
+                    }),
+                ));
 
-                let store_dead =
-                    Statement { source_info, kind: StatementKind::StorageDead(size_array_local) };
+                let store_dead = StatementKind::StorageDead(size_array_local);
 
-                let iter = [
+                let stmts = [
                     store_live,
                     const_assign,
                     store_discr,
@@ -191,14 +151,16 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                     deinit_old,
                     copy_bytes,
                     store_dead,
-                ]
-                .into_iter();
+                ];
+                for stmt in stmts {
+                    patch.add_statement(location, stmt);
+                }
 
                 st.make_nop();
-
-                Some(iter)
-            });
+            }
         }
+
+        patch.apply(body);
     }
 
     fn is_required(&self) -> bool {
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index b4f6fa514a4..d3d181f6cb2 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -4,11 +4,12 @@ use rustc_middle::ty::Ty;
 use rustc_span::Span;
 use tracing::debug;
 
-/// This struct represents a patch to MIR, which can add
-/// new statements and basic blocks and patch over block
-/// terminators.
+/// This struct lets you "patch" a MIR body, i.e. modify it. You can queue up
+/// various changes, such as the addition of new statements and basic blocks
+/// and replacement of terminators, and then apply the queued changes all at
+/// once with `apply`. This is useful for MIR transformation passes.
 pub(crate) struct MirPatch<'tcx> {
-    patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
+    term_patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
     new_blocks: Vec<BasicBlockData<'tcx>>,
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
     new_locals: Vec<LocalDecl<'tcx>>,
@@ -24,9 +25,10 @@ pub(crate) struct MirPatch<'tcx> {
 }
 
 impl<'tcx> MirPatch<'tcx> {
+    /// Creates a new, empty patch.
     pub(crate) fn new(body: &Body<'tcx>) -> Self {
         let mut result = MirPatch {
-            patch_map: IndexVec::from_elem(None, &body.basic_blocks),
+            term_patch_map: IndexVec::from_elem(None, &body.basic_blocks),
             new_blocks: vec![],
             new_statements: vec![],
             new_locals: vec![],
@@ -141,10 +143,12 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool {
-        self.patch_map[bb].is_some()
+    /// Has a replacement of this block's terminator been queued in this patch?
+    pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool {
+        self.term_patch_map[bb].is_some()
     }
 
+    /// Queues the addition of a new temporary with additional local info.
     pub(crate) fn new_local_with_info(
         &mut self,
         ty: Ty<'tcx>,
@@ -159,6 +163,7 @@ impl<'tcx> MirPatch<'tcx> {
         Local::new(index)
     }
 
+    /// Queues the addition of a new temporary.
     pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
         let index = self.next_local;
         self.next_local += 1;
@@ -174,29 +179,46 @@ impl<'tcx> MirPatch<'tcx> {
         self.new_locals[new_local_idx].ty
     }
 
+    /// Queues the addition of a new basic block.
     pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
-        let block = BasicBlock::new(self.patch_map.len());
+        let block = BasicBlock::new(self.term_patch_map.len());
         debug!("MirPatch: new_block: {:?}: {:?}", block, data);
         self.new_blocks.push(data);
-        self.patch_map.push(None);
+        self.term_patch_map.push(None);
         block
     }
 
+    /// Queues the replacement of a block's terminator.
     pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
-        assert!(self.patch_map[block].is_none());
+        assert!(self.term_patch_map[block].is_none());
         debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
-        self.patch_map[block] = Some(new);
+        self.term_patch_map[block] = Some(new);
     }
 
+    /// Queues the insertion of a statement at a given location. The statement
+    /// currently at that location, and all statements that follow, are shifted
+    /// down. If multiple statements are queued for addition at the same
+    /// location, the final statement order after calling `apply` will match
+    /// the queue insertion order.
+    ///
+    /// E.g. if we have `s0` at location `loc` and do these calls:
+    ///
+    ///   p.add_statement(loc, s1);
+    ///   p.add_statement(loc, s2);
+    ///   p.apply(body);
+    ///
+    /// then the final order will be `s1, s2, s0`, with `s1` at `loc`.
     pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
         debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
         self.new_statements.push((loc, stmt));
     }
 
+    /// Like `add_statement`, but specialized for assignments.
     pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
         self.add_statement(loc, StatementKind::Assign(Box::new((place, rv))));
     }
 
+    /// Applies the queued changes.
     pub(crate) fn apply(self, body: &mut Body<'tcx>) {
         debug!(
             "MirPatch: {:?} new temps, starting from index {}: {:?}",
@@ -209,14 +231,14 @@ impl<'tcx> MirPatch<'tcx> {
             self.new_blocks.len(),
             body.basic_blocks.len()
         );
-        let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() {
+        let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() {
             body.basic_blocks.as_mut_preserves_cfg()
         } else {
             body.basic_blocks.as_mut()
         };
         bbs.extend(self.new_blocks);
         body.local_decls.extend(self.new_locals);
-        for (src, patch) in self.patch_map.into_iter_enumerated() {
+        for (src, patch) in self.term_patch_map.into_iter_enumerated() {
             if let Some(patch) = patch {
                 debug!("MirPatch: patching block {:?}", src);
                 bbs[src].terminator_mut().kind = patch;
@@ -224,6 +246,9 @@ impl<'tcx> MirPatch<'tcx> {
         }
 
         let mut new_statements = self.new_statements;
+
+        // This must be a stable sort to provide the ordering described in the
+        // comment for `add_statement`.
         new_statements.sort_by_key(|s| s.0);
 
         let mut delta = 0;
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index c5e951eb8b2..02caa92ad3f 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -48,9 +48,11 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
 
             // We're only changing an operand, not the terminator kinds or successors
             let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
-            let init_statement =
-                basic_blocks[init_loc.block].statements[init_loc.statement_index].replace_nop();
-            let StatementKind::Assign(place_and_rvalue) = init_statement.kind else {
+            let init_statement_kind = std::mem::replace(
+                &mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind,
+                StatementKind::Nop,
+            );
+            let StatementKind::Assign(place_and_rvalue) = init_statement_kind else {
                 bug!("No longer an assign?");
             };
             let (place, rvalue) = *place_and_rvalue;
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 36cd3e00b76..8e93bdc61d0 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,9 +1,8 @@
 //! This module ensures that if a function's ABI requires a particular target feature,
 //! that target feature is enabled both on the callee and all callers.
-use rustc_abi::{BackendRepr, RegKind};
+use rustc_abi::{BackendRepr, ExternAbi, RegKind};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::{self, traversal};
-use rustc_middle::ty::inherent::*;
 use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
 use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
 use rustc_span::def_id::DefId;
@@ -97,7 +96,7 @@ fn check_call_site_abi<'tcx>(
     span: Span,
     caller: InstanceKind<'tcx>,
 ) {
-    if callee.fn_sig(tcx).abi().is_rust() {
+    if callee.fn_sig(tcx).abi() == ExternAbi::Rust {
         // "Rust" ABI never passes arguments in vector registers.
         return;
     }
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 451c215566b..eacb6002f5a 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 derive-where = "1.2.7"
-rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
@@ -22,7 +21,6 @@ nightly = [
     "dep:rustc_data_structures",
     "dep:rustc_macros",
     "dep:rustc_serialize",
-    "rustc_ast_ir/nightly",
     "rustc_index/nightly",
     "rustc_type_ir/nightly",
 ]
diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
index d8c1dc8b4e9..0fc313e33b3 100644
--- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
@@ -34,7 +34,17 @@ where
     ) -> QueryResult<I> {
         let cx = self.cx();
         let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
-        debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some());
+
+        // Check that the alias-relate goal is reasonable. Writeback for
+        // `coroutine_stalled_predicates` can replace alias terms with
+        // `{type error}` if the alias still contains infer vars, so we also
+        // accept alias-relate goals where one of the terms is an error.
+        debug_assert!(
+            lhs.to_alias_term().is_some()
+                || rhs.to_alias_term().is_some()
+                || lhs.is_error()
+                || rhs.is_error()
+        );
 
         // Structurally normalize the lhs.
         let lhs = if let Some(alias) = lhs.to_alias_term() {
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index b0f59ed1474..bfb590e8767 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -791,7 +791,7 @@ where
             return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Ambiguity));
         };
 
-        let responses: Vec<_> = match proven_via {
+        match proven_via {
             // Even when a trait bound has been proven using a where-bound, we
             // still need to consider alias-bounds for normalization, see
             // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
@@ -800,7 +800,7 @@ where
             // constness checking. Doing so is *at least theoretically* breaking,
             // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
             TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
-                let mut candidates_from_env: Vec<_> = candidates
+                let mut candidates_from_env_and_bounds: Vec<_> = candidates
                     .iter()
                     .filter(|c| {
                         matches!(
@@ -813,16 +813,37 @@ where
 
                 // If the trait goal has been proven by using the environment, we want to treat
                 // aliases as rigid if there are no applicable projection bounds in the environment.
-                if candidates_from_env.is_empty() {
+                if candidates_from_env_and_bounds.is_empty() {
                     if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
-                        candidates_from_env.push(response);
+                        candidates_from_env_and_bounds.push(response);
                     }
                 }
-                candidates_from_env
+
+                if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
+                    Ok(response)
+                } else {
+                    self.flounder(&candidates_from_env_and_bounds)
+                }
             }
-            TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
-        };
+            TraitGoalProvenVia::Misc => {
+                // Prefer "orphaned" param-env normalization predicates, which are used
+                // (for example, and ideally only) when proving item bounds for an impl.
+                let candidates_from_env: Vec<_> = candidates
+                    .iter()
+                    .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+                    .map(|c| c.result)
+                    .collect();
+                if let Some(response) = self.try_merge_responses(&candidates_from_env) {
+                    return Ok(response);
+                }
 
-        self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok)
+                let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
+                if let Some(response) = self.try_merge_responses(&responses) {
+                    Ok(response)
+                } else {
+                    self.flounder(&responses)
+                }
+            }
+        }
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 082c356cc5f..dc0f4c4483e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -2,12 +2,11 @@
 //! traits, `Copy`/`Clone`.
 
 use derive_where::derive_where;
-use rustc_ast_ir::{Movability, Mutability};
 use rustc_type_ir::data_structures::HashMap;
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate};
+use rustc_type_ir::{self as ty, Interner, Movability, Mutability, Upcast as _, elaborate};
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use tracing::instrument;
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index dabfa5cc04c..1665dbb3018 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -1,13 +1,14 @@
 //! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
 
-use rustc_ast_ir::Movability;
 use rustc_type_ir::data_structures::IndexSet;
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::solve::CanonicalResponse;
 use rustc_type_ir::visit::TypeVisitableExt as _;
-use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
+use rustc_type_ir::{
+    self as ty, Interner, Movability, TraitPredicate, TypingMode, Upcast as _, elaborate,
+};
 use tracing::{instrument, trace};
 
 use crate::delegate::SolverDelegate;
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 72aebb5d121..67abc2d5394 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -301,13 +301,6 @@ impl<'a> Parser<'a> {
         &mut self,
         recover: bool,
     ) -> PResult<'a, (Ident, IdentIsRaw)> {
-        if let TokenKind::DocComment(..) = self.prev_token.kind {
-            return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything {
-                span: self.prev_token.span,
-                missing_comma: None,
-            }));
-        }
-
         let valid_follow = &[
             TokenKind::Eq,
             TokenKind::Colon,
@@ -319,6 +312,15 @@ impl<'a> Parser<'a> {
             TokenKind::CloseDelim(Delimiter::Brace),
             TokenKind::CloseDelim(Delimiter::Parenthesis),
         ];
+        if let TokenKind::DocComment(..) = self.prev_token.kind
+            && valid_follow.contains(&self.token.kind)
+        {
+            let err = self.dcx().create_err(DocCommentDoesNotDocumentAnything {
+                span: self.prev_token.span,
+                missing_comma: None,
+            });
+            return Err(err);
+        }
 
         let mut recovered_ident = None;
         // we take this here so that the correct original token is retained in
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5111a025f94..74c48a45f18 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1431,37 +1431,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Warns against some misuses of `#[must_use]`
     fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
-        if !matches!(
+        if matches!(
             target,
             Target::Fn
                 | Target::Enum
                 | Target::Struct
                 | Target::Union
-                | Target::Method(_)
+                | Target::Method(MethodKind::Trait { body: false } | MethodKind::Inherent)
                 | Target::ForeignFn
                 // `impl Trait` in return position can trip
                 // `unused_must_use` if `Trait` is marked as
                 // `#[must_use]`
                 | Target::Trait
         ) {
-            let article = match target {
-                Target::ExternCrate
-                | Target::Enum
-                | Target::Impl
-                | Target::Expression
-                | Target::Arm
-                | Target::AssocConst
-                | Target::AssocTy => "an",
-                _ => "a",
-            };
+            return;
+        }
 
-            self.tcx.emit_node_span_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr.span,
-                errors::MustUseNoEffect { article, target },
-            );
+        // `#[must_use]` can be applied to a trait method definition with a default body
+        if let Target::Method(MethodKind::Trait { body: true }) = target
+            && let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id
+            && let containing_item = self.tcx.hir().expect_item(parent_def_id)
+            && let hir::ItemKind::Trait(..) = containing_item.kind
+        {
+            return;
         }
+
+        let article = match target {
+            Target::ExternCrate
+            | Target::Enum
+            | Target::Impl
+            | Target::Expression
+            | Target::Arm
+            | Target::AssocConst
+            | Target::AssocTy => "an",
+            _ => "a",
+        };
+
+        self.tcx.emit_node_span_lint(
+            UNUSED_ATTRIBUTES,
+            hir_id,
+            attr.span,
+            errors::MustUseNoEffect { article, target },
+        );
     }
 
     /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b1b234eb757..46e52e1f131 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -182,6 +182,19 @@ pub(crate) struct ImportData<'ra> {
 /// so we can use referential equality to compare them.
 pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>;
 
+// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
+// contained data.
+// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
+// are upheld.
+impl std::hash::Hash for ImportData<'_> {
+    fn hash<H>(&self, _: &mut H)
+    where
+        H: std::hash::Hasher,
+    {
+        unreachable!()
+    }
+}
+
 impl<'ra> ImportData<'ra> {
     pub(crate) fn is_glob(&self) -> bool {
         matches!(self.kind, ImportKind::Glob { .. })
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 0962865e7f1..b37c684a055 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -8,7 +8,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
 use rustc_ast::{
     self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
-    Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind,
+    Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@@ -1529,7 +1529,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     Applicability::MaybeIncorrect,
                 );
                 true
-            } else if kind == DefKind::Struct
+            } else if matches!(kind, DefKind::Struct | DefKind::TyAlias)
                 && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
                 && let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
             {
@@ -1566,7 +1566,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
         };
 
-        let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| {
+        let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| {
             let (followed_by_brace, closing_brace) = this.followed_by_brace(span);
 
             match source {
@@ -1740,12 +1740,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 }
             }
             (
-                Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
+                Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _),
                 PathSource::Expr(Some(parent)),
-            ) => {
-                if !path_sep(self, err, parent, kind) {
-                    return false;
-                }
+            ) if path_sep(self, err, parent, kind) => {
+                return true;
             }
             (
                 Res::Def(DefKind::Enum, def_id),
@@ -1777,13 +1775,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
                     if let PathSource::Expr(Some(parent)) = source {
                         if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
-                            bad_struct_syntax_suggestion(self, def_id);
+                            bad_struct_syntax_suggestion(self, err, def_id);
                             return true;
                         }
                     }
                     struct_ctor
                 } else {
-                    bad_struct_syntax_suggestion(self, def_id);
+                    bad_struct_syntax_suggestion(self, err, def_id);
                     return true;
                 };
 
@@ -1861,7 +1859,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 err.span_label(span, "constructor is not visible here due to private fields");
             }
             (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
-                bad_struct_syntax_suggestion(self, def_id);
+                bad_struct_syntax_suggestion(self, err, def_id);
             }
             (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
                 match source {
@@ -2471,31 +2469,73 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         def_id: DefId,
         span: Span,
     ) {
-        let Some(variants) = self.collect_enum_ctors(def_id) else {
+        let Some(variant_ctors) = self.collect_enum_ctors(def_id) else {
             err.note("you might have meant to use one of the enum's variants");
             return;
         };
 
-        let suggest_only_tuple_variants =
-            matches!(source, PathSource::TupleStruct(..)) || source.is_call();
-        if suggest_only_tuple_variants {
+        // If the expression is a field-access or method-call, try to find a variant with the field/method name
+        // that could have been intended, and suggest replacing the `.` with `::`.
+        // Otherwise, suggest adding `::VariantName` after the enum;
+        // and if the expression is call-like, only suggest tuple variants.
+        let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source {
+            // `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`.
+            PathSource::TupleStruct(..) => (None, true),
+            PathSource::Expr(Some(expr)) => match &expr.kind {
+                // `Type(a, b)`, only suggest adding a tuple variant after `Type`.
+                ExprKind::Call(..) => (None, true),
+                // `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant,
+                // otherwise suggest adding a variant after `Type`.
+                ExprKind::MethodCall(box MethodCall {
+                    receiver,
+                    span,
+                    seg: PathSegment { ident, .. },
+                    ..
+                }) => {
+                    let dot_span = receiver.span.between(*span);
+                    let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| {
+                        *ctor_kind == CtorKind::Fn
+                            && path.segments.last().is_some_and(|seg| seg.ident == *ident)
+                    });
+                    (found_tuple_variant.then_some(dot_span), false)
+                }
+                // `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant,
+                // otherwise suggest adding a variant after `Type`.
+                ExprKind::Field(base, ident) => {
+                    let dot_span = base.span.between(ident.span);
+                    let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| {
+                        path.segments.last().is_some_and(|seg| seg.ident == *ident)
+                    });
+                    (found_tuple_or_unit_variant.then_some(dot_span), false)
+                }
+                _ => (None, false),
+            },
+            _ => (None, false),
+        };
+
+        if let Some(dot_span) = suggest_path_sep_dot_span {
+            err.span_suggestion_verbose(
+                dot_span,
+                "use the path separator to refer to a variant",
+                "::",
+                Applicability::MaybeIncorrect,
+            );
+        } else if suggest_only_tuple_variants {
             // Suggest only tuple variants regardless of whether they have fields and do not
             // suggest path with added parentheses.
-            let mut suggestable_variants = variants
+            let mut suggestable_variants = variant_ctors
                 .iter()
                 .filter(|(.., kind)| *kind == CtorKind::Fn)
                 .map(|(variant, ..)| path_names_to_string(variant))
                 .collect::<Vec<_>>();
             suggestable_variants.sort();
 
-            let non_suggestable_variant_count = variants.len() - suggestable_variants.len();
+            let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len();
 
-            let source_msg = if source.is_call() {
-                "to construct"
-            } else if matches!(source, PathSource::TupleStruct(..)) {
+            let source_msg = if matches!(source, PathSource::TupleStruct(..)) {
                 "to match against"
             } else {
-                unreachable!()
+                "to construct"
             };
 
             if !suggestable_variants.is_empty() {
@@ -2514,7 +2554,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
 
             // If the enum has no tuple variants..
-            if non_suggestable_variant_count == variants.len() {
+            if non_suggestable_variant_count == variant_ctors.len() {
                 err.help(format!("the enum has no tuple variants {source_msg}"));
             }
 
@@ -2537,7 +2577,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 }
             };
 
-            let mut suggestable_variants = variants
+            let mut suggestable_variants = variant_ctors
                 .iter()
                 .filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@@ -2564,7 +2604,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 );
             }
 
-            let mut suggestable_variants_with_placeholders = variants
+            let mut suggestable_variants_with_placeholders = variant_ctors
                 .iter()
                 .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 90191b7776f..5bc37e09f08 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -589,6 +589,19 @@ struct ModuleData<'ra> {
 #[rustc_pass_by_value]
 struct Module<'ra>(Interned<'ra, ModuleData<'ra>>);
 
+// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
+// contained data.
+// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
+// are upheld.
+impl std::hash::Hash for ModuleData<'_> {
+    fn hash<H>(&self, _: &mut H)
+    where
+        H: std::hash::Hasher,
+    {
+        unreachable!()
+    }
+}
+
 impl<'ra> ModuleData<'ra> {
     fn new(
         parent: Option<Module<'ra>>,
@@ -739,6 +752,19 @@ struct NameBindingData<'ra> {
 /// so we can use referential equality to compare them.
 type NameBinding<'ra> = Interned<'ra, NameBindingData<'ra>>;
 
+// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
+// contained data.
+// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
+// are upheld.
+impl std::hash::Hash for NameBindingData<'_> {
+    fn hash<H>(&self, _: &mut H)
+    where
+        H: std::hash::Hasher,
+    {
+        unreachable!()
+    }
+}
+
 trait ToNameBinding<'ra> {
     fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra>;
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index fb2e838cdc9..a627e0e69b6 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -202,7 +202,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         match *self {
-            rustc_abi::BackendRepr::Uninhabited => ValueAbi::Uninhabited,
             rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
             rustc_abi::BackendRepr::ScalarPair(first, second) => {
                 ValueAbi::ScalarPair(first.stable(tables), second.stable(tables))
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 94039089480..d4d435d9b74 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -192,6 +192,7 @@ symbols! {
         Capture,
         Cell,
         Center,
+        Child,
         Cleanup,
         Clone,
         CoercePointee,
@@ -288,6 +289,7 @@ symbols! {
         OsString,
         Output,
         Param,
+        ParamSet,
         PartialEq,
         PartialOrd,
         Path,
@@ -336,6 +338,7 @@ symbols! {
         SliceIter,
         Some,
         SpanCtxt,
+        Stdin,
         String,
         StructuralPartialEq,
         SubdiagMessage,
@@ -518,6 +521,7 @@ symbols! {
         bang,
         begin_panic,
         bench,
+        bevy_ecs,
         bikeshed_guaranteed_no_drop,
         bin,
         binaryheap_iter,
@@ -599,6 +603,9 @@ symbols! {
         cfi,
         cfi_encoding,
         char,
+        char_is_ascii,
+        child_id,
+        child_kill,
         client,
         clippy,
         clobber_abi,
@@ -1468,6 +1475,7 @@ symbols! {
         panic_2015,
         panic_2021,
         panic_abort,
+        panic_any,
         panic_bounds_check,
         panic_cannot_unwind,
         panic_const_add_overflow,
@@ -1573,6 +1581,7 @@ symbols! {
         proc_macro_mod,
         proc_macro_non_items,
         proc_macro_path_invoc,
+        process_abort,
         process_exit,
         profiler_builtins,
         profiler_runtime,
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index 47566bde6b4..3fa67c624a7 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -80,7 +80,7 @@ where
                 }
             }
         },
-        BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv),
+        BackendRepr::Vector { .. } => return Err(CannotUseFpConv),
         BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields {
             FieldsShape::Primitive => {
                 unreachable!("aggregates can't have `FieldsShape::Primitive`")
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 2bde1055622..1c044fe98b3 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -7,7 +7,7 @@ use rustc_abi::{
 };
 use rustc_macros::HashStable_Generic;
 
-use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
+use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi};
 
 mod aarch64;
 mod amdgpu;
@@ -38,7 +38,7 @@ mod xtensa;
 pub enum PassMode {
     /// Ignore the argument.
     ///
-    /// The argument is either uninhabited or a ZST.
+    /// The argument is a ZST.
     Ignore,
     /// Pass the argument directly.
     ///
@@ -350,7 +350,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, Scalar, Size) -> ArgAttributes,
     ) -> Self {
         let mode = match layout.backend_repr {
-            BackendRepr::Uninhabited => PassMode::Ignore,
             BackendRepr::Scalar(scalar) => {
                 PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO))
             }
@@ -386,6 +385,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     /// Pass this argument directly instead. Should NOT be used!
     /// Only exists because of past ABI mistakes that will take time to fix
     /// (see <https://github.com/rust-lang/rust/issues/115666>).
+    #[track_caller]
     pub fn make_direct_deprecated(&mut self) {
         match self.mode {
             PassMode::Indirect { .. } => {
@@ -398,6 +398,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
 
     /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead.
     /// This is valid for both sized and unsized arguments.
+    #[track_caller]
     pub fn make_indirect(&mut self) {
         match self.mode {
             PassMode::Direct(_) | PassMode::Pair(_, _) => {
@@ -412,6 +413,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
 
     /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass
     /// ZSTs indirectly.
+    #[track_caller]
     pub fn make_indirect_from_ignore(&mut self) {
         match self.mode {
             PassMode::Ignore => {
@@ -716,7 +718,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
         C: HasDataLayout + HasTargetSpec,
     {
         let spec = cx.target_spec();
-        match &spec.arch[..] {
+        match &*spec.arch {
             "x86" => x86::compute_rust_abi_info(cx, self, abi),
             "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
             "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
@@ -724,6 +726,24 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             _ => {}
         };
 
+        // Decides whether we can pass the given SIMD argument via `PassMode::Direct`.
+        // May only return `true` if the target will always pass those arguments the same way,
+        // no matter what the user does with `-Ctarget-feature`! In other words, whatever
+        // target features are required to pass a SIMD value in registers must be listed in
+        // the `abi_required_features` for the current target and ABI.
+        let can_pass_simd_directly = |arg: &ArgAbi<'_, Ty>| match &*spec.arch {
+            // On x86, if we have SSE2 (which we have by default for x86_64), we can always pass up
+            // to 128-bit-sized vectors.
+            "x86" if spec.rustc_abi == Some(RustcAbi::X86Sse2) => arg.layout.size.bits() <= 128,
+            "x86_64" if spec.rustc_abi != Some(RustcAbi::X86Softfloat) => {
+                // FIXME once https://github.com/bytecodealliance/wasmtime/issues/10254 is fixed
+                // accept vectors up to 128bit rather than vectors of exactly 128bit.
+                arg.layout.size.bits() == 128
+            }
+            // So far, we haven't implemented this logic for any other target.
+            _ => false,
+        };
+
         for (arg_idx, arg) in self
             .args
             .iter_mut()
@@ -731,12 +751,15 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             .map(|(idx, arg)| (Some(idx), arg))
             .chain(iter::once((None, &mut self.ret)))
         {
-            if arg.is_ignore() {
+            // If the logic above already picked a specific type to cast the argument to, leave that
+            // in place.
+            if matches!(arg.mode, PassMode::Ignore | PassMode::Cast { .. }) {
                 continue;
             }
 
             if arg_idx.is_none()
                 && arg.layout.size > Primitive::Pointer(AddressSpace::DATA).size(cx) * 2
+                && !matches!(arg.layout.backend_repr, BackendRepr::Vector { .. })
             {
                 // Return values larger than 2 registers using a return area
                 // pointer. LLVM and Cranelift disagree about how to return
@@ -746,7 +769,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 // return value independently and decide to pass it in a
                 // register or not, which would result in the return value
                 // being passed partially in registers and partially through a
-                // return area pointer.
+                // return area pointer. For large IR-level values such as `i128`,
+                // cranelift will even split up the value into smaller chunks.
                 //
                 // While Cranelift may need to be fixed as the LLVM behavior is
                 // generally more correct with respect to the surface language,
@@ -776,53 +800,60 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 // rustc_target already ensure any return value which doesn't
                 // fit in the available amount of return registers is passed in
                 // the right way for the current target.
+                //
+                // The adjustment is not necessary nor desired for types with a vector
+                // representation; those are handled below.
                 arg.make_indirect();
                 continue;
             }
 
             match arg.layout.backend_repr {
-                BackendRepr::Memory { .. } => {}
-
-                // This is a fun case! The gist of what this is doing is
-                // that we want callers and callees to always agree on the
-                // ABI of how they pass SIMD arguments. If we were to *not*
-                // make these arguments indirect then they'd be immediates
-                // in LLVM, which means that they'd used whatever the
-                // appropriate ABI is for the callee and the caller. That
-                // means, for example, if the caller doesn't have AVX
-                // enabled but the callee does, then passing an AVX argument
-                // across this boundary would cause corrupt data to show up.
-                //
-                // This problem is fixed by unconditionally passing SIMD
-                // arguments through memory between callers and callees
-                // which should get them all to agree on ABI regardless of
-                // target feature sets. Some more information about this
-                // issue can be found in #44367.
-                //
-                // Note that the intrinsic ABI is exempt here as
-                // that's how we connect up to LLVM and it's unstable
-                // anyway, we control all calls to it in libstd.
-                BackendRepr::Vector { .. }
-                    if abi != ExternAbi::RustIntrinsic && spec.simd_types_indirect =>
-                {
-                    arg.make_indirect();
-                    continue;
+                BackendRepr::Memory { .. } => {
+                    // Compute `Aggregate` ABI.
+
+                    let is_indirect_not_on_stack =
+                        matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
+                    assert!(is_indirect_not_on_stack);
+
+                    let size = arg.layout.size;
+                    if arg.layout.is_sized()
+                        && size <= Primitive::Pointer(AddressSpace::DATA).size(cx)
+                    {
+                        // We want to pass small aggregates as immediates, but using
+                        // an LLVM aggregate type for this leads to bad optimizations,
+                        // so we pick an appropriately sized integer type instead.
+                        arg.cast_to(Reg { kind: RegKind::Integer, size });
+                    }
                 }
 
-                _ => continue,
-            }
-            // Compute `Aggregate` ABI.
-
-            let is_indirect_not_on_stack =
-                matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
-            assert!(is_indirect_not_on_stack);
-
-            let size = arg.layout.size;
-            if !arg.layout.is_unsized() && size <= Primitive::Pointer(AddressSpace::DATA).size(cx) {
-                // We want to pass small aggregates as immediates, but using
-                // an LLVM aggregate type for this leads to bad optimizations,
-                // so we pick an appropriately sized integer type instead.
-                arg.cast_to(Reg { kind: RegKind::Integer, size });
+                BackendRepr::Vector { .. } => {
+                    // This is a fun case! The gist of what this is doing is
+                    // that we want callers and callees to always agree on the
+                    // ABI of how they pass SIMD arguments. If we were to *not*
+                    // make these arguments indirect then they'd be immediates
+                    // in LLVM, which means that they'd used whatever the
+                    // appropriate ABI is for the callee and the caller. That
+                    // means, for example, if the caller doesn't have AVX
+                    // enabled but the callee does, then passing an AVX argument
+                    // across this boundary would cause corrupt data to show up.
+                    //
+                    // This problem is fixed by unconditionally passing SIMD
+                    // arguments through memory between callers and callees
+                    // which should get them all to agree on ABI regardless of
+                    // target feature sets. Some more information about this
+                    // issue can be found in #44367.
+                    //
+                    // Note that the intrinsic ABI is exempt here as those are not
+                    // real functions anyway, and the backend expects very specific types.
+                    if abi != ExternAbi::RustIntrinsic
+                        && spec.simd_types_indirect
+                        && !can_pass_simd_directly(arg)
+                    {
+                        arg.make_indirect();
+                    }
+                }
+
+                _ => {}
             }
         }
     }
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index 265ae20f991..785175229b0 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -86,7 +86,7 @@ where
                 }
             }
         },
-        BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv),
+        BackendRepr::Vector { .. } => return Err(CannotUseFpConv),
         BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields {
             FieldsShape::Primitive => {
                 unreachable!("aggregates can't have `FieldsShape::Primitive`")
diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs
index 5b9414536d8..7e5aab0201b 100644
--- a/compiler/rustc_target/src/callconv/x86.rs
+++ b/compiler/rustc_target/src/callconv/x86.rs
@@ -4,7 +4,7 @@ use rustc_abi::{
 };
 
 use crate::callconv::{ArgAttribute, FnAbi, PassMode};
-use crate::spec::HasTargetSpec;
+use crate::spec::{HasTargetSpec, RustcAbi};
 
 #[derive(PartialEq)]
 pub(crate) enum Flavor {
@@ -108,9 +108,7 @@ where
                 Ty: TyAbiInterface<'a, C> + Copy,
             {
                 match layout.backend_repr {
-                    BackendRepr::Uninhabited
-                    | BackendRepr::Scalar(_)
-                    | BackendRepr::ScalarPair(..) => false,
+                    BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) => false,
                     BackendRepr::Vector { .. } => true,
                     BackendRepr::Memory { .. } => {
                         for i in 0..layout.fields.count() {
@@ -236,8 +234,16 @@ where
             _ => false, // anyway not passed via registers on x86
         };
         if has_float {
-            if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) {
-                // Same size or smaller than pointer, return in a register.
+            if cx.target_spec().rustc_abi == Some(RustcAbi::X86Sse2)
+                && fn_abi.ret.layout.backend_repr.is_scalar()
+                && fn_abi.ret.layout.size.bits() <= 128
+            {
+                // This is a single scalar that fits into an SSE register, and the target uses the
+                // SSE ABI. We prefer this over integer registers as float scalars need to be in SSE
+                // registers for float operations, so that's the best place to pass them around.
+                fn_abi.ret.cast_to(Reg { kind: RegKind::Vector, size: fn_abi.ret.layout.size });
+            } else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) {
+                // Same size or smaller than pointer, return in an integer register.
                 fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size });
             } else {
                 // Larger than a pointer, return indirectly.
diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs
index b15d82c26da..ab306e20239 100644
--- a/compiler/rustc_target/src/callconv/x86_64.rs
+++ b/compiler/rustc_target/src/callconv/x86_64.rs
@@ -51,8 +51,6 @@ where
         }
 
         let mut c = match layout.backend_repr {
-            BackendRepr::Uninhabited => return Ok(()),
-
             BackendRepr::Scalar(scalar) => match scalar.primitive() {
                 Primitive::Int(..) | Primitive::Pointer(_) => Class::Int,
                 Primitive::Float(_) => Class::Sse,
diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs
index 23ef2cf8284..4d99a9f9ba0 100644
--- a/compiler/rustc_target/src/callconv/x86_win64.rs
+++ b/compiler/rustc_target/src/callconv/x86_win64.rs
@@ -1,14 +1,14 @@
 use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size};
 
 use crate::callconv::{ArgAbi, FnAbi, Reg};
-use crate::spec::HasTargetSpec;
+use crate::spec::{HasTargetSpec, RustcAbi};
 
 // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
 
-pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
+pub(crate) fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
     let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| {
         match a.layout.backend_repr {
-            BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
+            BackendRepr::Memory { sized: false } => {}
             BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
                 match a.layout.size.bits() {
                     8 => a.cast_to(Reg::i8()),
@@ -24,10 +24,14 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<
             }
             BackendRepr::Scalar(scalar) => {
                 if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
-                    // `i128` is returned in xmm0 by Clang and GCC
-                    // FIXME(#134288): This may change for the `-msvc` targets in the future.
-                    let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
-                    a.cast_to(reg);
+                    if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) {
+                        // Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing.
+                    } else {
+                        // `i128` is returned in xmm0 by Clang and GCC
+                        // FIXME(#134288): This may change for the `-msvc` targets in the future.
+                        let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
+                        a.cast_to(reg);
+                    }
                 } else if a.layout.size.bytes() > 8
                     && !matches!(scalar.primitive(), Primitive::Float(Float::F128))
                 {
diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr.rs
index 3554dcfcb4a..85b73e61e52 100644
--- a/compiler/rustc_target/src/spec/base/avr_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/avr.rs
@@ -1,45 +1,5 @@
 use object::elf;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
-
-/// A base target for AVR devices using the GNU toolchain.
-///
-/// Requires GNU avr-gcc and avr-binutils on the host system.
-/// FIXME: Remove the second parameter when const string concatenation is possible.
-pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
-    Target {
-        arch: "avr".into(),
-        metadata: crate::spec::TargetMetadata {
-            description: None,
-            tier: None,
-            host_tools: None,
-            std: None,
-        },
-        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
-        llvm_target: "avr-unknown-unknown".into(),
-        pointer_width: 16,
-        options: TargetOptions {
-            env: "gnu".into(),
-
-            c_int_width: "16".into(),
-            cpu: target_cpu.into(),
-            exe_suffix: ".elf".into(),
-
-            linker: Some("avr-gcc".into()),
-            eh_frame_header: false,
-            pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
-            late_link_args: TargetOptions::link_args(
-                LinkerFlavor::Gnu(Cc::Yes, Lld::No),
-                &["-lgcc"],
-            ),
-            max_atomic_width: Some(16),
-            atomic_cas: false,
-            relocation_model: RelocModel::Static,
-            ..TargetOptions::default()
-        },
-    }
-}
-
 /// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the
 /// name of the target CPU / MCU.
 ///
diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs
index b9139c8452c..6f88be5d37f 100644
--- a/compiler/rustc_target/src/spec/base/mod.rs
+++ b/compiler/rustc_target/src/spec/base/mod.rs
@@ -1,7 +1,7 @@
 pub(crate) mod aix;
 pub(crate) mod android;
 pub(crate) mod apple;
-pub(crate) mod avr_gnu;
+pub(crate) mod avr;
 pub(crate) mod bpf;
 pub(crate) mod cygwin;
 pub(crate) mod dragonfly;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index f7e467b0c11..65736770efb 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -60,7 +60,7 @@ pub mod crt_objects;
 mod base;
 mod json;
 
-pub use base::avr_gnu::ef_avr_arch;
+pub use base::avr::ef_avr_arch;
 
 /// Linker is called through a C/C++ compiler.
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -303,15 +303,16 @@ impl LinkerFlavor {
         }
     }
 
-    fn infer_linker_hints(linker_stem: &str) -> (Option<Cc>, Option<Lld>) {
+    fn infer_linker_hints(linker_stem: &str) -> Result<Self, (Option<Cc>, Option<Lld>)> {
         // Remove any version postfix.
         let stem = linker_stem
             .rsplit_once('-')
             .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
             .unwrap_or(linker_stem);
 
-        // GCC/Clang can have an optional target prefix.
-        if stem == "emcc"
+        if stem == "llvm-bitcode-linker" {
+            Ok(Self::Llbc)
+        } else if stem == "emcc" // GCC/Clang can have an optional target prefix.
             || stem == "gcc"
             || stem.ends_with("-gcc")
             || stem == "g++"
@@ -321,7 +322,7 @@ impl LinkerFlavor {
             || stem == "clang++"
             || stem.ends_with("-clang++")
         {
-            (Some(Cc::Yes), Some(Lld::No))
+            Err((Some(Cc::Yes), Some(Lld::No)))
         } else if stem == "wasm-ld"
             || stem.ends_with("-wasm-ld")
             || stem == "ld.lld"
@@ -329,11 +330,11 @@ impl LinkerFlavor {
             || stem == "rust-lld"
             || stem == "lld-link"
         {
-            (Some(Cc::No), Some(Lld::Yes))
+            Err((Some(Cc::No), Some(Lld::Yes)))
         } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
-            (Some(Cc::No), Some(Lld::No))
+            Err((Some(Cc::No), Some(Lld::No)))
         } else {
-            (None, None)
+            Err((None, None))
         }
     }
 
@@ -357,7 +358,10 @@ impl LinkerFlavor {
     }
 
     pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
-        self.with_hints(LinkerFlavor::infer_linker_hints(linker_stem))
+        match LinkerFlavor::infer_linker_hints(linker_stem) {
+            Ok(linker_flavor) => linker_flavor,
+            Err(hints) => self.with_hints(hints),
+        }
     }
 
     pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
@@ -1797,7 +1801,7 @@ supported_targets! {
     ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
     ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
 
-    ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
+    ("avr-none", avr_none),
 
     ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
 
@@ -2001,7 +2005,7 @@ supported_targets! {
     ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
     ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
     ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
-    ("i586-pc-nto-qnx700", i586_pc_nto_qnx700),
+    ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
 
     ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
     ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
@@ -3062,7 +3066,10 @@ impl Target {
             &self.post_link_args,
         ] {
             for (&flavor, flavor_args) in args {
-                check!(!flavor_args.is_empty(), "linker flavor args must not be empty");
+                check!(
+                    !flavor_args.is_empty() || self.arch == "avr",
+                    "linker flavor args must not be empty"
+                );
                 // Check that flavors mentioned in link args are compatible with the default flavor.
                 match self.linker_flavor {
                     LinkerFlavor::Gnu(..) => {
diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs
new file mode 100644
index 00000000000..91d3197d099
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/avr_none.rs
@@ -0,0 +1,32 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
+
+pub(crate) fn target() -> Target {
+    Target {
+        arch: "avr".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
+        llvm_target: "avr-unknown-unknown".into(),
+        pointer_width: 16,
+        options: TargetOptions {
+            c_int_width: "16".into(),
+            exe_suffix: ".elf".into(),
+            linker: Some("avr-gcc".into()),
+            eh_frame_header: false,
+            pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[]),
+            late_link_args: TargetOptions::link_args(
+                LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+                &["-lgcc"],
+            ),
+            max_atomic_width: Some(16),
+            atomic_cas: false,
+            relocation_model: RelocModel::Static,
+            need_explicit_cpu: true,
+            ..TargetOptions::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs
deleted file mode 100644
index c3d6fb72273..00000000000
--- a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-use crate::spec::{Target, base};
-
-pub(crate) fn target() -> Target {
-    base::avr_gnu::target("atmega328", "-mmcu=atmega328")
-}
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs
index 6a98a763b36..6a98a763b36 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index b13a753c4ed..2f2361609a2 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2021"
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 2bb38f3ed14..42b8199cb26 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -18,7 +18,6 @@ use rustc_middle::ty::{
     TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
 };
 use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
-use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
 use tracing::{debug, instrument, warn};
 
@@ -217,7 +216,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
                                 // `_` because then we'd end up with `Vec<_, _>`, instead of
                                 // `Vec<_>`.
                                 arg
-                            } else if let GenericArgKind::Type(_) = arg.kind() {
+                            } else if let GenericArgKind::Type(_) = arg.unpack() {
                                 // We don't replace lifetime or const params, only type params.
                                 self.new_infer().into()
                             } else {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index d009687ef14..fecb38ab597 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -2,7 +2,7 @@ use std::iter;
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{
-    Applicability, Diag, E0309, E0310, E0311, E0495, Subdiagnostic, struct_span_code_err,
+    Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err,
 };
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -1032,7 +1032,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         struct_span_code_err!(
             self.dcx(),
             var_origin.span(),
-            E0495,
+            E0803,
             "cannot infer an appropriate lifetime{} due to conflicting requirements",
             var_description
         )
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 3d89b6ed2f0..ee0ab0dfbb8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3289,6 +3289,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let mut parent_trait_pred =
                     self.resolve_vars_if_possible(data.derived.parent_trait_pred);
                 let parent_def_id = parent_trait_pred.def_id();
+                if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id)
+                    && !tcx.features().enabled(sym::try_trait_v2)
+                {
+                    // If `#![feature(try_trait_v2)]` is not enabled, then there's no point on
+                    // talking about `FromResidual<Result<A, B>>`, as the end user has nothing they
+                    // can do about it. As far as they are concerned, `?` is compiler magic.
+                    return;
+                }
                 let self_ty_str =
                     tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
                 let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 9fbc1d64d74..4b1bc316d5f 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -11,12 +11,11 @@
 
 use std::assert_matches::assert_matches;
 
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
+use rustc_middle::ty::visit::{VisitorResult, try_visit};
 use rustc_middle::ty::{TyCtxt, TypeFoldable};
 use rustc_middle::{bug, ty};
 use rustc_next_trait_solver::resolve::EagerResolver;
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 92098e20448..f04a5feba30 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_infer::traits::query::type_op::DropckOutlives;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::Span;
 use tracing::{debug, instrument};
 
+use crate::solve::NextSolverError;
 use crate::traits::query::NoSolution;
 use crate::traits::query::normalize::QueryNormalizeExt;
-use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
+use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt};
 
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
@@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
     goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
     span: Span,
 ) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
+    match compute_dropck_outlives_with_errors(ocx, goal, span) {
+        Ok(r) => Ok(r),
+        Err(_) => Err(NoSolution),
+    }
+}
+
+pub fn compute_dropck_outlives_with_errors<'tcx, E>(
+    ocx: &ObligationCtxt<'_, 'tcx, E>,
+    goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
+    span: Span,
+) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let tcx = ocx.infcx.tcx;
     let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
 
@@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         dtorck_constraint_for_ty_inner(
             tcx,
             ocx.infcx.typing_env(param_env),
-            DUMMY_SP,
+            span,
             depth,
             ty,
             &mut constraints,
-        )?;
+        );
 
         // "outlives" represent types/regions that may be touched
         // by a destructor.
@@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         // do not themselves define a destructor", more or less. We have
         // to push them onto the stack to be expanded.
         for ty in constraints.dtorck_types.drain(..) {
-            let Normalized { value: ty, obligations } =
-                ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
-            ocx.register_obligations(obligations);
+            let ty = if let Ok(Normalized { value: ty, obligations }) =
+                ocx.infcx.at(&cause, param_env).query_normalize(ty)
+            {
+                ocx.register_obligations(obligations);
+
+                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                ty
+            } else {
+                ocx.deeply_normalize(&cause, param_env, ty)?;
 
-            debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                let errors = ocx.select_where_possible();
+                debug!("normalize errors: {ty} ~> {errors:#?}");
+                return Err(errors);
+            };
 
             match ty.kind() {
                 // All parameters live for the duration of the
@@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
     depth: usize,
     ty: Ty<'tcx>,
     constraints: &mut DropckConstraint<'tcx>,
-) -> Result<(), NoSolution> {
+) {
     if !tcx.recursion_limit().value_within_limit(depth) {
         constraints.overflows.push(ty);
-        return Ok(());
+        return;
     }
 
     if trivial_dropck_outlives(tcx, ty) {
-        return Ok(());
+        return;
     }
 
     match ty.kind() {
@@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // single-element containers, behave like their element
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
                 dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
-            })?;
+            });
         }
 
         ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in tys.iter() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in args.as_closure().upvar_tys() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::CoroutineClosure(_, args) => {
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
                         depth + 1,
                         ty,
                         constraints,
-                    )?;
+                    );
                 }
-                Ok::<_, NoSolution>(())
-            })?
+            })
         }
 
         ty::Coroutine(_, args) => {
@@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
 
         ty::Adt(def, args) => {
             let DropckConstraint { dtorck_types, outlives, overflows } =
-                tcx.at(span).adt_dtorck_constraint(def.did())?;
+                tcx.at(span).adt_dtorck_constraint(def.did());
             // FIXME: we can try to recursively `dtorck_constraint_on_ty`
             // there, but that needs some way to handle cycles.
             constraints
@@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
         ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
-            return Err(NoSolution);
+            tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty));
         }
     }
-
-    Ok(())
 }
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index b3377e15aa7..5eddad39e2b 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -30,10 +30,7 @@ fn dropck_outlives<'tcx>(
 }
 
 /// Calculates the dtorck constraint for a type.
-pub(crate) fn adt_dtorck_constraint(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-) -> Result<&DropckConstraint<'_>, NoSolution> {
+pub(crate) fn adt_dtorck_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &DropckConstraint<'_> {
     let def = tcx.adt_def(def_id);
     let span = tcx.def_span(def_id);
     let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
@@ -52,20 +49,20 @@ pub(crate) fn adt_dtorck_constraint(
             overflows: vec![],
         };
         debug!("dtorck_constraint: {:?} => {:?}", def, result);
-        return Ok(tcx.arena.alloc(result));
+        return tcx.arena.alloc(result);
     }
 
     let mut result = DropckConstraint::empty();
     for field in def.all_fields() {
         let fty = tcx.type_of(field.did).instantiate_identity();
-        dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?;
+        dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result);
     }
     result.outlives.extend(tcx.destructor_constraints(def));
     dedup_dtorck_constraint(&mut result);
 
     debug!("dtorck_constraint: {:?} => {:?}", def, result);
 
-    Ok(tcx.arena.alloc(result))
+    tcx.arena.alloc(result)
 }
 
 fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) {
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index 6a98be18503..94c7695117c 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi", optional = true }
-rustc_ast_ir = { path = "../rustc_ast_ir", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir", optional = true }
 rustc_infer = { path = "../rustc_infer", optional = true }
@@ -19,7 +18,6 @@ tracing = "0.1"
 [features]
 rustc = [
     "dep:rustc_abi",
-    "dep:rustc_ast_ir",
     "dep:rustc_hir",
     "dep:rustc_infer",
     "dep:rustc_macros",
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index f88f8c38d50..ab903c6ed73 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 # tidy-alphabetical-start
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index c5d2d0afbfa..0ff82f0c256 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -464,7 +464,7 @@ fn fn_abi_sanity_check<'tcx>(
 
         match &arg.mode {
             PassMode::Ignore => {
-                assert!(arg.layout.is_zst() || arg.layout.is_uninhabited());
+                assert!(arg.layout.is_zst());
             }
             PassMode::Direct(_) => {
                 // Here the Rust type is used to determine the actual ABI, so we have to be very
@@ -472,9 +472,7 @@ fn fn_abi_sanity_check<'tcx>(
                 // `layout.backend_repr` and ignore everything else. We should just reject
                 //`Aggregate` entirely here, but some targets need to be fixed first.
                 match arg.layout.backend_repr {
-                    BackendRepr::Uninhabited
-                    | BackendRepr::Scalar(_)
-                    | BackendRepr::Vector { .. } => {}
+                    BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => {}
                     BackendRepr::ScalarPair(..) => {
                         panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty)
                     }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 8429e68b600..b6a14d147ca 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -134,42 +134,32 @@ fn univariant_uninterned<'tcx>(
     cx: &LayoutCx<'tcx>,
     ty: Ty<'tcx>,
     fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>,
-    repr: &ReprOptions,
     kind: StructKind,
 ) -> Result<LayoutData<FieldIdx, VariantIdx>, &'tcx LayoutError<'tcx>> {
-    let pack = repr.pack;
-    if pack.is_some() && repr.align.is_some() {
-        cx.tcx().dcx().bug("struct cannot be packed and aligned");
-    }
-
-    cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
+    let repr = ReprOptions::default();
+    cx.calc.univariant(fields, &repr, kind).map_err(|err| map_error(cx, ty, err))
 }
 
 fn extract_const_value<'tcx>(
-    const_: ty::Const<'tcx>,
-    ty: Ty<'tcx>,
     cx: &LayoutCx<'tcx>,
+    ty: Ty<'tcx>,
+    ct: ty::Const<'tcx>,
 ) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
-    match const_.kind() {
+    match ct.kind() {
         ty::ConstKind::Value(cv) => Ok(cv),
-        ty::ConstKind::Error(guar) => {
-            return Err(error(cx, LayoutError::ReferencesError(guar)));
-        }
-        ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
-            if !const_.has_param() {
-                bug!("no generic type found in the type: {ty:?}");
-            }
-            return Err(error(cx, LayoutError::TooGeneric(ty)));
-        }
-        ty::ConstKind::Unevaluated(_) => {
-            if !const_.has_param() {
-                return Err(error(cx, LayoutError::Unknown(ty)));
-            } else {
-                return Err(error(cx, LayoutError::TooGeneric(ty)));
+        ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => {
+            if !ct.has_param() {
+                bug!("failed to normalize const, but it is not generic: {ct:?}");
             }
+            Err(error(cx, LayoutError::TooGeneric(ty)))
         }
-        ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
-            bug!("unexpected type: {ty:?}");
+        ty::ConstKind::Infer(_)
+        | ty::ConstKind::Bound(..)
+        | ty::ConstKind::Placeholder(_)
+        | ty::ConstKind::Error(_) => {
+            // `ty::ConstKind::Error` is handled at the top of `layout_of_uncached`
+            // (via `ty.error_reported()`).
+            bug!("layout_of: unexpected const: {ct:?}");
         }
     }
 }
@@ -194,10 +184,9 @@ fn layout_of_uncached<'tcx>(
     };
     let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value)));
 
-    let univariant =
-        |fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>, repr: &ReprOptions, kind| {
-            Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
-        };
+    let univariant = |fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>, kind| {
+        Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, kind)?))
+    };
     debug_assert!(!ty.has_non_region_infer());
 
     Ok(match *ty.kind() {
@@ -210,12 +199,12 @@ fn layout_of_uncached<'tcx>(
                         &mut layout.backend_repr
                     {
                         if let Some(start) = start {
-                            scalar.valid_range_mut().start = extract_const_value(start, ty, cx)?
+                            scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
                                 .try_to_bits(tcx, cx.typing_env)
                                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                         }
                         if let Some(end) = end {
-                            let mut end = extract_const_value(end, ty, cx)?
+                            let mut end = extract_const_value(cx, ty, end)?
                                 .try_to_bits(tcx, cx.typing_env)
                                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                             if !include_end {
@@ -274,16 +263,11 @@ fn layout_of_uncached<'tcx>(
                 data_ptr.valid_range_mut().start = 1;
             }
 
-            let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee);
             if pointee.is_sized(tcx, cx.typing_env) {
                 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
             }
 
-            let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
-                // Projection eagerly bails out when the pointee references errors,
-                // fall back to structurally deducing metadata.
-                && !pointee.references_error()
-            {
+            let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
                 let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
                 let metadata_ty =
                     match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) {
@@ -354,7 +338,7 @@ fn layout_of_uncached<'tcx>(
 
         // Arrays and slices.
         ty::Array(element, count) => {
-            let count = extract_const_value(count, ty, cx)?
+            let count = extract_const_value(cx, ty, count)?
                 .try_to_target_usize(tcx)
                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
 
@@ -364,19 +348,17 @@ fn layout_of_uncached<'tcx>(
                 .checked_mul(count, dl)
                 .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
 
-            let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) {
-                BackendRepr::Uninhabited
-            } else {
-                BackendRepr::Memory { sized: true }
-            };
+            let abi = BackendRepr::Memory { sized: true };
 
             let largest_niche = if count != 0 { element.largest_niche } else { None };
+            let uninhabited = if count != 0 { element.uninhabited } else { false };
 
             tcx.mk_layout(LayoutData {
                 variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr: abi,
                 largest_niche,
+                uninhabited,
                 align: element.align,
                 size,
                 max_repr_align: None,
@@ -391,6 +373,7 @@ fn layout_of_uncached<'tcx>(
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
+                uninhabited: false,
                 align: element.align,
                 size: Size::ZERO,
                 max_repr_align: None,
@@ -406,6 +389,7 @@ fn layout_of_uncached<'tcx>(
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
+            uninhabited: false,
             align: dl.i8_align,
             size: Size::ZERO,
             max_repr_align: None,
@@ -415,17 +399,10 @@ fn layout_of_uncached<'tcx>(
         }),
 
         // Odd unit types.
-        ty::FnDef(..) => {
-            univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)?
-        }
+        ty::FnDef(..) => univariant(IndexSlice::empty(), StructKind::AlwaysSized)?,
         ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
-            let mut unit = univariant_uninterned(
-                cx,
-                ty,
-                IndexSlice::empty(),
-                &ReprOptions::default(),
-                StructKind::AlwaysSized,
-            )?;
+            let mut unit =
+                univariant_uninterned(cx, ty, IndexSlice::empty(), StructKind::AlwaysSized)?;
             match unit.backend_repr {
                 BackendRepr::Memory { ref mut sized } => *sized = false,
                 _ => bug!(),
@@ -439,7 +416,6 @@ fn layout_of_uncached<'tcx>(
             let tys = args.as_closure().upvar_tys();
             univariant(
                 &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
-                &ReprOptions::default(),
                 StructKind::AlwaysSized,
             )?
         }
@@ -448,7 +424,6 @@ fn layout_of_uncached<'tcx>(
             let tys = args.as_coroutine_closure().upvar_tys();
             univariant(
                 &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
-                &ReprOptions::default(),
                 StructKind::AlwaysSized,
             )?
         }
@@ -457,11 +432,7 @@ fn layout_of_uncached<'tcx>(
             let kind =
                 if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
 
-            univariant(
-                &tys.iter().map(|k| cx.layout_of(k)).try_collect::<IndexVec<_, _>>()?,
-                &ReprOptions::default(),
-                kind,
-            )?
+            univariant(&tys.iter().map(|k| cx.layout_of(k)).try_collect::<IndexVec<_, _>>()?, kind)?
         }
 
         // SIMD vector types.
@@ -584,6 +555,7 @@ fn layout_of_uncached<'tcx>(
                 fields,
                 backend_repr: abi,
                 largest_niche: e_ly.largest_niche,
+                uninhabited: false,
                 size,
                 align,
                 max_repr_align: None,
@@ -719,25 +691,30 @@ fn layout_of_uncached<'tcx>(
         }
 
         // Types with no meaningful known layout.
+        ty::Param(_) => {
+            return Err(error(cx, LayoutError::TooGeneric(ty)));
+        }
+
         ty::Alias(..) => {
-            if ty.has_param() {
-                return Err(error(cx, LayoutError::TooGeneric(ty)));
-            }
             // NOTE(eddyb) `layout_of` query should've normalized these away,
             // if that was possible, so there's no reason to try again here.
-            return Err(error(cx, LayoutError::Unknown(ty)));
-        }
-
-        ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
-            bug!("Layout::compute: unexpected type `{}`", ty)
-        }
-
-        ty::Param(_) => {
-            return Err(error(cx, LayoutError::TooGeneric(ty)));
+            let err = if ty.has_param() {
+                LayoutError::TooGeneric(ty)
+            } else {
+                // This is only reachable with unsatisfiable predicates. For example, if we have
+                // `u8: Iterator`, then we can't compute the layout of `<u8 as Iterator>::Item`.
+                LayoutError::Unknown(ty)
+            };
+            return Err(error(cx, err));
         }
 
-        ty::Placeholder(..) => {
-            return Err(error(cx, LayoutError::Unknown(ty)));
+        ty::Placeholder(..)
+        | ty::Bound(..)
+        | ty::CoroutineWitness(..)
+        | ty::Infer(_)
+        | ty::Error(_) => {
+            // `ty::Error` is handled at the top of this function.
+            bug!("layout_of: unexpected type `{ty}`")
         }
     })
 }
@@ -911,13 +888,7 @@ fn coroutine_layout<'tcx>(
         .chain(iter::once(Ok(tag_layout)))
         .chain(promoted_layouts)
         .try_collect::<IndexVec<_, _>>()?;
-    let prefix = univariant_uninterned(
-        cx,
-        ty,
-        &prefix_layouts,
-        &ReprOptions::default(),
-        StructKind::AlwaysSized,
-    )?;
+    let prefix = univariant_uninterned(cx, ty, &prefix_layouts, StructKind::AlwaysSized)?;
 
     let (prefix_size, prefix_align) = (prefix.size, prefix.align);
 
@@ -982,7 +953,6 @@ fn coroutine_layout<'tcx>(
                 cx,
                 ty,
                 &variant_only_tys.map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
-                &ReprOptions::default(),
                 StructKind::Prefixed(prefix_size, prefix_align.abi),
             )?;
             variant.variants = Variants::Single { index };
@@ -1045,13 +1015,8 @@ fn coroutine_layout<'tcx>(
 
     size = size.align_to(align.abi);
 
-    let abi = if prefix.backend_repr.is_uninhabited()
-        || variants.iter().all(|v| v.backend_repr.is_uninhabited())
-    {
-        BackendRepr::Uninhabited
-    } else {
-        BackendRepr::Memory { sized: true }
-    };
+    let uninhabited = prefix.uninhabited || variants.iter().all(|v| v.is_uninhabited());
+    let abi = BackendRepr::Memory { sized: true };
 
     // this is similar to how ReprOptions populates its field_shuffle_seed
     let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash();
@@ -1072,6 +1037,7 @@ fn coroutine_layout<'tcx>(
         // See <https://github.com/rust-lang/rust/issues/63818>, <https://github.com/rust-lang/miri/issues/3780>.
         // FIXME: Remove when <https://github.com/rust-lang/rust/issues/125735> is implemented and aliased coroutine fields are wrapped in `UnsafePinned`.
         largest_niche: None,
+        uninhabited,
         size,
         align,
         max_repr_align: None,
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index 8d5403ed324..5ea6716c5ca 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -10,7 +10,11 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
 
     // Type-level uninhabitedness should always imply ABI uninhabitedness.
     if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) {
-        assert!(layout.is_uninhabited());
+        assert!(
+            layout.is_uninhabited(),
+            "{:?} is type-level uninhabited but not ABI-uninhabited?",
+            layout.ty
+        );
     }
 
     if layout.size.bytes() % layout.align.abi.bytes() != 0 {
@@ -71,7 +75,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
         let Some((align, size)) = align.zip(size) else {
             assert_matches!(
                 layout.layout.backend_repr(),
-                BackendRepr::Uninhabited | BackendRepr::Memory { .. },
+                BackendRepr::Memory { .. },
                 "ABI unexpectedly missing alignment and/or size in {layout:#?}"
             );
             return;
@@ -235,7 +239,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
                 assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
                 // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
             }
-            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check.
+            BackendRepr::Memory { .. } => {} // Nothing to check.
         }
     }
 
@@ -291,8 +295,8 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
                     || variant.is_uninhabited()
                 {
                     // These are never actually accessed anyway, so we can skip the coherence check
-                    // for them. They also fail that check, since they have
-                    // `Aggregate`/`Uninhabited` ABI even when the main type is
+                    // for them. They also fail that check, since they may have
+                    // a different ABI even when the main type is
                     // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
                     // 0, and sometimes, variants without fields have non-0 size.)
                     continue;
@@ -306,7 +310,6 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
                     (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => {
                         scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
                     }
-                    (BackendRepr::Uninhabited, _) => true,
                     (BackendRepr::Memory { .. }, _) => true,
                     _ => false,
                 };
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 64e5a609b2f..d6f9277813d 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -1,11 +1,10 @@
 //! This module contains helpers for walking all types of
 //! a signature, while preserving spans as much as possible
 
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::span_bug;
+use rustc_middle::ty::visit::{VisitorResult, try_visit};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::visit::TypeVisitable;
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 6924216bd26..9277226b718 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -126,6 +126,10 @@ pub trait Ty<I: Interner<Ty = Self>>:
         matches!(self.kind(), ty::Infer(ty::TyVar(_)))
     }
 
+    fn is_ty_error(self) -> bool {
+        matches!(self.kind(), ty::Error(_))
+    }
+
     fn is_floating_point(self) -> bool {
         matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_)))
     }
@@ -284,6 +288,10 @@ pub trait Const<I: Interner<Const = Self>>:
     fn is_ct_var(self) -> bool {
         matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
     }
+
+    fn is_ct_error(self) -> bool {
+        matches!(self.kind(), ty::ConstKind::Error(_))
+    }
 }
 
 pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
@@ -370,6 +378,13 @@ pub trait Term<I: Interner<Term = Self>>:
         }
     }
 
+    fn is_error(self) -> bool {
+        match self.kind() {
+            ty::TermKind::Ty(ty) => ty.is_ty_error(),
+            ty::TermKind::Const(ct) => ct.is_ct_error(),
+        }
+    }
+
     fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
         match self.kind() {
             ty::TermKind::Ty(ty) => match ty.kind() {
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index e7ca24178cb..15ef4e7d6c1 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -74,6 +74,7 @@ pub use opaque_ty::*;
 pub use predicate::*;
 pub use predicate_kind::*;
 pub use region_kind::*;
+pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
 pub use ty_info::*;
 pub use ty_kind::*;
 pub use upcast::*;
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index a12e9856304..119b658a2bf 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -45,8 +45,8 @@ use std::fmt;
 use std::ops::ControlFlow;
 use std::sync::Arc;
 
-use rustc_ast_ir::visit::VisitorResult;
-use rustc_ast_ir::{try_visit, walk_visitable_list};
+pub use rustc_ast_ir::visit::VisitorResult;
+pub use rustc_ast_ir::{try_visit, walk_visitable_list};
 use rustc_index::{Idx, IndexVec};
 use smallvec::SmallVec;
 use thin_vec::ThinVec;
@@ -224,6 +224,13 @@ impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix
     }
 }
 
+impl<I: Interner, T: TypeVisitable<I>, S> TypeVisitable<I> for indexmap::IndexSet<T, S> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
+    }
+}
+
 pub trait Flags {
     fn flags(&self) -> TypeFlags;
     fn outer_exclusive_binder(&self) -> ty::DebruijnIndex;
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index ede6dcd469c..640299c2167 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -45,12 +45,12 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok
     s.add_bounds(synstructure::AddBounds::Fields);
     let body_visit = s.each(|bind| {
         quote! {
-            match ::rustc_ast_ir::visit::VisitorResult::branch(
+            match ::rustc_type_ir::visit::VisitorResult::branch(
                 ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
             ) {
                 ::core::ops::ControlFlow::Continue(()) => {},
                 ::core::ops::ControlFlow::Break(r) => {
-                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                    return ::rustc_type_ir::visit::VisitorResult::from_residual(r);
                 },
             }
         }
@@ -65,7 +65,7 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok
                 __visitor: &mut __V
             ) -> __V::Result {
                 match *self { #body_visit }
-                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                <__V::Result as ::rustc_type_ir::visit::VisitorResult>::output()
             }
         },
     )
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index 861b6692b53..091f3e1a95e 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -227,7 +227,6 @@ pub enum TagEncoding {
 /// in terms of categories of C types there are ABI rules for.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum ValueAbi {
-    Uninhabited,
     Scalar(Scalar),
     ScalarPair(Scalar, Scalar),
     Vector {
@@ -244,10 +243,7 @@ impl ValueAbi {
     /// Returns `true` if the layout corresponds to an unsized type.
     pub fn is_unsized(&self) -> bool {
         match *self {
-            ValueAbi::Uninhabited
-            | ValueAbi::Scalar(_)
-            | ValueAbi::ScalarPair(..)
-            | ValueAbi::Vector { .. } => false,
+            ValueAbi::Scalar(_) | ValueAbi::ScalarPair(..) | ValueAbi::Vector { .. } => false,
             ValueAbi::Aggregate { sized } => !sized,
         }
     }
diff --git a/config.example.toml b/config.example.toml
index fd27b24e461..a17d3ec9f88 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -793,12 +793,12 @@
 # C compiler to be used to compile C code. Note that the
 # default value is platform specific, and if not specified it may also depend on
 # what platform is crossing to what platform.
-# See `src/bootstrap/cc_detect.rs` for details.
+# See `src/bootstrap/src/utils/cc_detect.rs` for details.
 #cc = "cc" (path)
 
 # C++ compiler to be used to compile C++ code (e.g. LLVM and our LLVM shims).
 # This is only used for host targets.
-# See `src/bootstrap/cc_detect.rs` for details.
+# See `src/bootstrap/src/utils/cc_detect.rs` for details.
 #cxx = "c++" (path)
 
 # Archiver to be used to assemble static libraries compiled from C/C++ code.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 1bb0f761064..b16d40e988e 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -105,6 +105,7 @@
 #![feature(box_uninit_write)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
+#![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(coerce_unsized)]
 #![feature(const_eval_select)]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 154da691078..9446afd4b24 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1419,7 +1419,9 @@ impl String {
     pub fn push(&mut self, ch: char) {
         match ch.len_utf8() {
             1 => self.vec.push(ch as u8),
-            _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
+            _ => {
+                self.vec.extend_from_slice(ch.encode_utf8(&mut [0; char::MAX_LEN_UTF8]).as_bytes())
+            }
         }
     }
 
@@ -1716,7 +1718,7 @@ impl String {
     #[rustc_confusables("set")]
     pub fn insert(&mut self, idx: usize, ch: char) {
         assert!(self.is_char_boundary(idx));
-        let mut bits = [0; 4];
+        let mut bits = [0; char::MAX_LEN_UTF8];
         let bits = ch.encode_utf8(&mut bits).as_bytes();
 
         unsafe {
@@ -2797,7 +2799,7 @@ impl SpecToString for core::ascii::Char {
 impl SpecToString for char {
     #[inline]
     fn spec_to_string(&self) -> String {
-        String::from(self.encode_utf8(&mut [0; 4]))
+        String::from(self.encode_utf8(&mut [0; char::MAX_LEN_UTF8]))
     }
 }
 
@@ -3155,6 +3157,24 @@ impl From<String> for Vec<u8> {
     }
 }
 
+#[stable(feature = "try_from_vec_u8_for_string", since = "CURRENT_RUSTC_VERSION")]
+impl TryFrom<Vec<u8>> for String {
+    type Error = FromUtf8Error;
+    /// Converts the given [`Vec<u8>`] into a  [`String`] if it contains valid UTF-8 data.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s1 = b"hello world".to_vec();
+    /// let v1 = String::try_from(s1).unwrap();
+    /// assert_eq!(v1, "hello world");
+    ///
+    /// ```
+    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
+        Self::from_utf8(bytes)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Write for String {
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 1bcec4037cd..f95be6a6df0 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -3,6 +3,7 @@
 #![feature(iter_array_chunks)]
 #![feature(assert_matches)]
 #![feature(btree_extract_if)]
+#![feature(char_max_len)]
 #![feature(cow_is_borrowed)]
 #![feature(core_intrinsics)]
 #![feature(downcast_unchecked)]
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 23a0e5e5256..906fa2d425e 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -2,6 +2,7 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
+use std::char::MAX_LEN_UTF8;
 use std::cmp::Ordering::{Equal, Greater, Less};
 use std::str::{from_utf8, from_utf8_unchecked};
 
@@ -1231,7 +1232,7 @@ fn test_to_uppercase_rev_iterator() {
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_decoding() {
-    let mut bytes = [0; 4];
+    let mut bytes = [0; MAX_LEN_UTF8];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
         let s = c.encode_utf8(&mut bytes);
         if Some(c) != s.chars().next() {
@@ -1243,7 +1244,7 @@ fn test_chars_decoding() {
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_rev_decoding() {
-    let mut bytes = [0; 4];
+    let mut bytes = [0; MAX_LEN_UTF8];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
         let s = c.encode_utf8(&mut bytes);
         if Some(c) != s.chars().rev().next() {
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index ccfdbf0eb70..85cc315626d 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -71,6 +71,16 @@ impl char {
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const MAX: char = '\u{10FFFF}';
 
+    /// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
+    /// UTF-8 encoding.
+    #[unstable(feature = "char_max_len", issue = "121714")]
+    pub const MAX_LEN_UTF8: usize = 4;
+
+    /// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
+    /// to UTF-16 encoding.
+    #[unstable(feature = "char_max_len", issue = "121714")]
+    pub const MAX_LEN_UTF16: usize = 2;
+
     /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
     /// decoding error.
     ///
@@ -1168,6 +1178,7 @@ impl char {
     #[must_use]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "char_is_ascii")]
     #[inline]
     pub const fn is_ascii(&self) -> bool {
         *self as u32 <= 0x7F
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 59fd7250e8f..088c709f1a2 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -95,6 +95,16 @@ const MAX_THREE_B: u32 = 0x10000;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: char = char::MAX;
 
+/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
+/// UTF-8 encoding.
+#[unstable(feature = "char_max_len", issue = "121714")]
+pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
+
+/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
+/// to UTF-16 encoding.
+#[unstable(feature = "char_max_len", issue = "121714")]
+pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
+
 /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
 /// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
 #[stable(feature = "decode_utf16", since = "1.9.0")]
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index a1bf3a4d7a7..764e7fff33e 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -3,7 +3,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
-use crate::char::EscapeDebugExtArgs;
+use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
 use crate::marker::PhantomData;
 use crate::num::fmt as numfmt;
 use crate::ops::Deref;
@@ -187,7 +187,7 @@ pub trait Write {
     /// ```
     #[stable(feature = "fmt_write_char", since = "1.1.0")]
     fn write_char(&mut self, c: char) -> Result {
-        self.write_str(c.encode_utf8(&mut [0; 4]))
+        self.write_str(c.encode_utf8(&mut [0; MAX_LEN_UTF8]))
     }
 
     /// Glue for usage of the [`write!`] macro with implementors of this trait.
@@ -2768,7 +2768,7 @@ impl Display for char {
         if f.options.width.is_none() && f.options.precision.is_none() {
             f.write_char(*self)
         } else {
-            f.pad(self.encode_utf8(&mut [0; 4]))
+            f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8]))
         }
     }
 }
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 0c388115908..8090c98e7ed 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -556,13 +556,13 @@ impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoe
 ///     * `std::iter::ExactSizeIterator::len`
 ///     * `std::iter::Iterator::__iterator_get_unchecked`
 ///     * `std::iter::TrustedRandomAccessNoCoerce::size`
-/// 5. If `T` is a subtype of `Self`, then `self` is allowed to be coerced
+/// 5. If `Self` is a subtype of `T`, then `self` is allowed to be coerced
 ///    to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
 ///    been called, then no methods except for the ones listed under 4. are allowed to be called
 ///    on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
 ///    Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
 ///    called on `self` and the resulting value of type `T` (and on further coercion results with
-///    sub-subtypes) are added together and their sums must not exceed the specified bounds.
+///    super-supertypes) are added together and their sums must not exceed the specified bounds.
 ///
 /// Further, given that these conditions are met, it must guarantee that:
 ///
@@ -570,7 +570,7 @@ impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoe
 /// * It must be safe to call the methods listed above on `self` after calling
 ///   `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
 /// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
-/// * If `T` is a subtype of `Self`, then it must be safe to coerce `self` to `T`.
+/// * If `Self` is a subtype of `T`, then it must be safe to coerce `self` to `T`.
 //
 // FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner`
 // after `__iterator_get_unchecked` is supposed to be allowed.
@@ -580,7 +580,7 @@ impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoe
 pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {}
 
 /// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around
-/// coercions to subtypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
+/// coercions to supertypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
 /// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`.
 ///
 /// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions.
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 96a290ad5a0..296b5ebdfaf 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -193,13 +193,13 @@ macro_rules! int_impl {
         /// Basic usage:
         ///
         /// ```
-        /// #![feature(integer_sign_cast)]
         ///
         #[doc = concat!("let n = -1", stringify!($SelfT), ";")]
         ///
         #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")]
         /// ```
-        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 55f4ccd958e..80a38a6013d 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -163,14 +163,14 @@ macro_rules! midpoint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(num_midpoint_signed)]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
         #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")]
         #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
         /// ```
-        #[unstable(feature = "num_midpoint_signed", issue = "110840")]
+        #[stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -215,14 +215,14 @@ macro_rules! midpoint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(num_midpoint_signed)]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
         #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")]
         #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")]
         #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
         /// ```
-        #[unstable(feature = "num_midpoint_signed", issue = "110840")]
+        #[stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 21bad6705ab..b59451d7c75 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -1633,14 +1633,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// Basic usage:
         ///
         /// ```
-        /// #![feature(integer_sign_cast)]
         /// # use std::num::NonZero;
         ///
         #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::MAX;")]
         ///
         #[doc = concat!("assert_eq!(n.cast_signed(), NonZero::new(-1", stringify!($Sint), ").unwrap());")]
         /// ```
-        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -2072,14 +2072,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// Basic usage:
         ///
         /// ```
-        /// #![feature(integer_sign_cast)]
         /// # use std::num::NonZero;
         ///
         #[doc = concat!("let n = NonZero::new(-1", stringify!($Int), ").unwrap();")]
         ///
         #[doc = concat!("assert_eq!(n.cast_unsigned(), NonZero::<", stringify!($Uint), ">::MAX);")]
         /// ```
-        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 29f6791ee6a..74d3ae699f6 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -223,13 +223,12 @@ macro_rules! uint_impl {
         /// Basic usage:
         ///
         /// ```
-        /// #![feature(integer_sign_cast)]
-        ///
         #[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")]
         ///
         #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")]
         /// ```
-        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 45e320e66bc..b1456a1bc1d 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -154,16 +154,39 @@ macro_rules! iterator {
 
             #[inline]
             fn next(&mut self) -> Option<$elem> {
-                // could be implemented with slices, but this avoids bounds checks
+                // intentionally not using the helpers because this is
+                // one of the most mono'd things in the library.
 
-                // SAFETY: The call to `next_unchecked` is
-                // safe since we check if the iterator is empty first.
+                let ptr = self.ptr;
+                let end_or_len = self.end_or_len;
+                // SAFETY: See inner comments. (For some reason having multiple
+                // block breaks inlining this -- if you can fix that please do!)
                 unsafe {
-                    if is_empty!(self) {
-                        None
+                    if T::IS_ZST {
+                        let len = end_or_len.addr();
+                        if len == 0 {
+                            return None;
+                        }
+                        // SAFETY: just checked that it's not zero, so subtracting one
+                        // cannot wrap.  (Ideally this would be `checked_sub`, which
+                        // does the same thing internally, but as of 2025-02 that
+                        // doesn't optimize quite as small in MIR.)
+                        self.end_or_len = without_provenance_mut(len.unchecked_sub(1));
                     } else {
-                        Some(self.next_unchecked())
+                        // SAFETY: by type invariant, the `end_or_len` field is always
+                        // non-null for a non-ZST pointee.  (This transmute ensures we
+                        // get `!nonnull` metadata on the load of the field.)
+                        if ptr == crate::intrinsics::transmute::<$ptr, NonNull<T>>(end_or_len) {
+                            return None;
+                        }
+                        // SAFETY: since it's not empty, per the check above, moving
+                        // forward one keeps us inside the slice, and this is valid.
+                        self.ptr = ptr.add(1);
                     }
+                    // SAFETY: Now that we know it wasn't empty and we've moved past
+                    // the first one (to avoid giving a duplicate `&mut` next time),
+                    // we can give out a reference to it.
+                    Some({ptr}.$into_ref())
                 }
             }
 
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ed45e26256e..7b9a76e814a 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4796,7 +4796,7 @@ impl<T, const N: usize> [[T; N]] {
     /// assert!(empty_slice_of_arrays.as_flattened().is_empty());
     /// ```
     #[stable(feature = "slice_flatten", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
+    #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_flattened(&self) -> &[T] {
         let len = if T::IS_ZST {
             self.len().checked_mul(N).expect("slice len overflow")
@@ -4833,7 +4833,7 @@ impl<T, const N: usize> [[T; N]] {
     /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
     /// ```
     #[stable(feature = "slice_flatten", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
+    #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_flattened_mut(&mut self) -> &mut [T] {
         let len = if T::IS_ZST {
             self.len().checked_mul(N).expect("slice len overflow")
diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs
index 09f898309bd..f6dcf42ba60 100644
--- a/library/core/src/slice/sort/shared/smallsort.rs
+++ b/library/core/src/slice/sort/shared/smallsort.rs
@@ -387,7 +387,7 @@ unsafe fn swap_if_less<T, F>(v_base: *mut T, a_pos: usize, b_pos: usize, is_less
 where
     F: FnMut(&T, &T) -> bool,
 {
-    // SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid
+    // SAFETY: the caller must guarantee that `a_pos` and `b_pos` each added to `v_base` yield valid
     // pointers into `v_base`, and are properly aligned, and part of the same allocation.
     unsafe {
         let v_a = v_base.add(a_pos);
@@ -404,16 +404,16 @@ where
         // The equivalent code with a branch would be:
         //
         // if should_swap {
-        //     ptr::swap(left, right, 1);
+        //     ptr::swap(v_a, v_b, 1);
         // }
 
         // The goal is to generate cmov instructions here.
-        let left_swap = if should_swap { v_b } else { v_a };
-        let right_swap = if should_swap { v_a } else { v_b };
+        let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
+        let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
 
-        let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap));
-        ptr::copy(left_swap, v_a, 1);
-        ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1);
+        let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
+        ptr::copy(v_a_swap, v_a, 1);
+        ptr::copy_nonoverlapping(&*v_b_swap_tmp, v_b, 1);
     }
 }
 
@@ -640,26 +640,21 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
         //  1,  1 |  c   b    a         d
         let c3 = is_less(&*c, &*a);
         let c4 = is_less(&*d, &*b);
-        let min = select(c3, c, a);
-        let max = select(c4, b, d);
-        let unknown_left = select(c3, a, select(c4, c, b));
-        let unknown_right = select(c4, d, select(c3, b, c));
+        let min = c3.select_unpredictable(c, a);
+        let max = c4.select_unpredictable(b, d);
+        let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
+        let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
 
         // Sort the last two unknown elements.
         let c5 = is_less(&*unknown_right, &*unknown_left);
-        let lo = select(c5, unknown_right, unknown_left);
-        let hi = select(c5, unknown_left, unknown_right);
+        let lo = c5.select_unpredictable(unknown_right, unknown_left);
+        let hi = c5.select_unpredictable(unknown_left, unknown_right);
 
         ptr::copy_nonoverlapping(min, dst, 1);
         ptr::copy_nonoverlapping(lo, dst.add(1), 1);
         ptr::copy_nonoverlapping(hi, dst.add(2), 1);
         ptr::copy_nonoverlapping(max, dst.add(3), 1);
     }
-
-    #[inline(always)]
-    fn select<T>(cond: bool, if_true: *const T, if_false: *const T) -> *const T {
-        if cond { if_true } else { if_false }
-    }
 }
 
 /// SAFETY: The caller MUST guarantee that `v_base` is valid for 8 reads and
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index fd2cd59f88e..4754d18b06e 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -198,8 +198,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // some bytes, in a vector
     /// let sparkle_heart = vec![240, 159, 146, 150];
     ///
@@ -207,14 +205,12 @@ impl str {
     /// let sparkle_heart = str::from_utf8(&sparkle_heart)?;
     ///
     /// assert_eq!("💖", sparkle_heart);
-    /// # Ok::<_, str::Utf8Error>(())
+    /// # Ok::<_, std::str::Utf8Error>(())
     /// ```
     ///
     /// Incorrect bytes:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // some invalid bytes, in a vector
     /// let sparkle_heart = vec![0, 159, 146, 150];
     ///
@@ -227,8 +223,6 @@ impl str {
     /// A "stack allocated string":
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // some bytes, in a stack-allocated array
     /// let sparkle_heart = [240, 159, 146, 150];
     ///
@@ -237,7 +231,8 @@ impl str {
     ///
     /// assert_eq!("💖", sparkle_heart);
     /// ```
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8"]
     pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
         converts::from_utf8(v)
@@ -250,8 +245,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // "Hello, Rust!" as a mutable vector
     /// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33];
     ///
@@ -264,8 +257,6 @@ impl str {
     /// Incorrect bytes:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // Some invalid bytes in a mutable vector
     /// let mut invalid = vec![128, 223];
     ///
@@ -273,7 +264,7 @@ impl str {
     /// ```
     /// See the docs for [`Utf8Error`] for more details on the kinds of
     /// errors that can be returned.
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_mut"]
     pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
@@ -294,8 +285,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// // some bytes, in a vector
     /// let sparkle_heart = vec![240, 159, 146, 150];
     ///
@@ -307,7 +296,8 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked"]
     pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
         // SAFETY: converts::from_utf8_unchecked has the same safety requirements as this function.
@@ -324,8 +314,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::str;
-    ///
     /// let mut heart = vec![240, 159, 146, 150];
     /// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) };
     ///
@@ -333,7 +321,8 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked_mut"]
     pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
         // SAFETY: converts::from_utf8_unchecked_mut has the same safety requirements as this function.
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 52e2364893e..2d941adfd85 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -38,6 +38,7 @@
     issue = "27721"
 )]
 
+use crate::char::MAX_LEN_UTF8;
 use crate::cmp::Ordering;
 use crate::convert::TryInto as _;
 use crate::slice::memchr;
@@ -561,8 +562,8 @@ impl Pattern for char {
     type Searcher<'a> = CharSearcher<'a>;
 
     #[inline]
-    fn into_searcher(self, haystack: &str) -> Self::Searcher<'_> {
-        let mut utf8_encoded = [0; 4];
+    fn into_searcher<'a>(self, haystack: &'a str) -> Self::Searcher<'a> {
+        let mut utf8_encoded = [0; MAX_LEN_UTF8];
         let utf8_size = self
             .encode_utf8(&mut utf8_encoded)
             .len()
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index b289f6026ff..9eb71922218 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -65,9 +65,9 @@ macro_rules! assert_unsafe_precondition {
             #[rustc_nounwind]
             const fn precondition_check($($name:$ty),*) {
                 if !$e {
-                    ::core::panicking::panic_nounwind(
-                        concat!("unsafe precondition(s) violated: ", $message)
-                    );
+                    ::core::panicking::panic_nounwind(concat!("unsafe precondition(s) violated: ", $message,
+                        "\n\nThis indicates a bug in the program. \
+                        This Undefined Behavior check is optional, and cannot be relied on for safety."));
                 }
             }
 
diff --git a/library/coretests/tests/char.rs b/library/coretests/tests/char.rs
index 6422387e956..153fb36925e 100644
--- a/library/coretests/tests/char.rs
+++ b/library/coretests/tests/char.rs
@@ -1,3 +1,4 @@
+use std::char::MAX_LEN_UTF8;
 use std::str::FromStr;
 use std::{char, str};
 
@@ -259,7 +260,7 @@ fn test_escape_unicode() {
 #[test]
 fn test_encode_utf8() {
     fn check(input: char, expect: &[u8]) {
-        let mut buf = [0; 4];
+        let mut buf = [0; MAX_LEN_UTF8];
         let ptr = buf.as_ptr();
         let s = input.encode_utf8(&mut buf);
         assert_eq!(s.as_ptr() as usize, ptr as usize);
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 1e1ff29e161..ca58f41d7dd 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -13,6 +13,7 @@
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
 #![feature(cell_update)]
+#![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(const_eval_select)]
 #![feature(const_swap_nonoverlapping)]
@@ -62,7 +63,6 @@
 #![feature(maybe_uninit_write_slice)]
 #![feature(min_specialization)]
 #![feature(never_type)]
-#![feature(num_midpoint_signed)]
 #![feature(numfmt)]
 #![feature(pattern)]
 #![feature(pointer_is_aligned_to)]
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index b763a7c75a5..19d45f4d3b3 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -401,7 +401,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a defaulted mask with all elements set to false (0)"]
     fn default() -> Self {
         Self::splat(false)
     }
@@ -413,7 +412,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new bool and does not mutate the original value"]
     fn eq(&self, other: &Self) -> bool {
         self.0 == other.0
     }
@@ -425,7 +423,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new Ordering and does not mutate the original value"]
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         self.0.partial_cmp(&other.0)
     }
@@ -451,7 +448,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Self) -> Self {
         Self(self.0 & rhs.0)
     }
@@ -464,7 +460,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: bool) -> Self {
         self & Self::splat(rhs)
     }
@@ -477,7 +472,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Mask<T, N>) -> Mask<T, N> {
         Mask::splat(self) & rhs
     }
@@ -490,7 +484,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Self) -> Self {
         Self(self.0 | rhs.0)
     }
@@ -503,7 +496,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: bool) -> Self {
         self | Self::splat(rhs)
     }
@@ -516,7 +508,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Mask<T, N>) -> Mask<T, N> {
         Mask::splat(self) | rhs
     }
@@ -529,7 +520,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Self) -> Self::Output {
         Self(self.0 ^ rhs.0)
     }
@@ -542,7 +532,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: bool) -> Self::Output {
         self ^ Self::splat(rhs)
     }
@@ -555,7 +544,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Mask<T, N>) -> Self::Output {
         Mask::splat(self) ^ rhs
     }
@@ -568,7 +556,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn not(self) -> Self::Output {
         Self(!self.0)
     }
diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
index 2d01946b574..387b508c4b4 100644
--- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
@@ -21,7 +21,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn clone(&self) -> Self {
         *self
     }
@@ -252,7 +251,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) }
@@ -266,7 +264,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) }
@@ -280,7 +277,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) }
@@ -294,7 +290,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn not(self) -> Self::Output {
         Self::splat(true) ^ self
     }
diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs
index d3bd14a3402..4ac64a253a3 100644
--- a/library/portable-simd/crates/core_simd/src/ops.rs
+++ b/library/portable-simd/crates/core_simd/src/ops.rs
@@ -135,7 +135,6 @@ macro_rules! for_base_types {
                     type Output = $out;
 
                     #[inline]
-                    #[must_use = "operator returns a new vector without mutating the inputs"]
                     // TODO: only useful for int Div::div, but we hope that this
                     // will essentially always get inlined anyway.
                     #[track_caller]
diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs
index 0ff76cfba39..913cbbe977c 100644
--- a/library/portable-simd/crates/core_simd/src/ops/deref.rs
+++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs
@@ -18,7 +18,6 @@ macro_rules! deref_lhs {
             type Output = Simd<T, N>;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the inputs"]
             fn $call(self, rhs: $simd) -> Self::Output {
                 (*self).$call(rhs)
             }
@@ -39,7 +38,6 @@ macro_rules! deref_rhs {
             type Output = Simd<T, N>;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the inputs"]
             fn $call(self, rhs: &$simd) -> Self::Output {
                 self.$call(*rhs)
             }
@@ -71,7 +69,6 @@ macro_rules! deref_ops {
                 type Output = $simd;
 
                 #[inline]
-                #[must_use = "operator returns a new vector without mutating the inputs"]
                 fn $call(self, rhs: &'rhs $simd) -> Self::Output {
                     (*self).$call(*rhs)
                 }
diff --git a/library/portable-simd/crates/core_simd/src/ops/unary.rs b/library/portable-simd/crates/core_simd/src/ops/unary.rs
index bdae96332a3..412a5b80117 100644
--- a/library/portable-simd/crates/core_simd/src/ops/unary.rs
+++ b/library/portable-simd/crates/core_simd/src/ops/unary.rs
@@ -11,7 +11,6 @@ macro_rules! neg {
             type Output = Self;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the input"]
             fn neg(self) -> Self::Output {
                 // Safety: `self` is a signed vector
                 unsafe { core::intrinsics::simd::simd_neg(self) }
@@ -46,7 +45,6 @@ macro_rules! not {
             type Output = Self;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the input"]
             fn not(self) -> Self::Output {
                 self ^ (Simd::splat(!(0 as $scalar)))
             }
diff --git a/library/portable-simd/crates/core_simd/src/simd/num/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs
index 79954b937b3..db705dfe202 100644
--- a/library/portable-simd/crates/core_simd/src/simd/num/float.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs
@@ -371,7 +371,6 @@ macro_rules! impl_trait {
             }
 
             #[inline]
-            #[must_use = "method returns a new mask and does not mutate the original value"]
             fn is_normal(self) -> Self::Mask {
                 !(self.abs().simd_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite())
             }
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index bdbe3e21994..0af69dff05a 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -1321,12 +1321,14 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_erf)]
+    /// # #[cfg(reliable_f16_math)] {
     /// let x: f16 = 0.123;
     ///
     /// let one = x.erf() + x.erfc();
     /// let abs_difference = (one - 1.0).abs();
     ///
     /// assert!(abs_difference <= f16::EPSILON);
+    /// # }
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 6001a2e2f39..57e235c3efe 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -624,20 +624,20 @@ impl File {
         self.inner.datasync()
     }
 
-    /// Acquire an exclusive advisory lock on the file. Blocks until the lock can be acquired.
+    /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired.
     ///
-    /// This acquires an exclusive advisory lock; no other file handle to this file may acquire
-    /// another lock.
+    /// This acquires an exclusive lock; no other file handle to this file may acquire another lock.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an advisory lock the exact
-    /// behavior is unspecified and platform dependent, including the possibility that it will
-    /// deadlock. However, if this method returns, then an exclusive lock is held.
+    /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
+    /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
+    /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
+    /// cause non-lockholders to block.
     ///
-    /// If the file not open for writing, it is unspecified whether this function returns an error.
+    /// If this file handle/descriptor, or a clone of it, already holds an lock the exact behavior
+    /// is unspecified and platform dependent, including the possibility that it will deadlock.
+    /// However, if this method returns, then an exclusive lock is held.
     ///
-    /// Note, this is an advisory lock meant to interact with [`lock_shared`], [`try_lock`],
-    /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
-    /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
+    /// If the file not open for writing, it is unspecified whether this function returns an error.
     ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
@@ -648,8 +648,12 @@ impl File {
     /// and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK` flag. Note that,
     /// this [may change in the future][changes].
     ///
+    /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,
+    /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.
+    ///
     /// [changes]: io#platform-specific-behavior
     ///
+    /// [`lock`]: File::lock
     /// [`lock_shared`]: File::lock_shared
     /// [`try_lock`]: File::try_lock
     /// [`try_lock_shared`]: File::try_lock_shared
@@ -660,7 +664,6 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -669,23 +672,24 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "file_lock", issue = "130994")]
+    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
     pub fn lock(&self) -> io::Result<()> {
         self.inner.lock()
     }
 
-    /// Acquire a shared (non-exclusive) advisory lock on the file. Blocks until the lock can be acquired.
+    /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired.
     ///
-    /// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but
-    /// none may hold an exclusive lock at the same time.
+    /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may
+    /// hold an exclusive lock at the same time.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact
-    /// behavior is unspecified and platform dependent, including the possibility that it will
-    /// deadlock. However, if this method returns, then a shared lock is held.
+    /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
+    /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
+    /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
+    /// cause non-lockholders to block.
     ///
-    /// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`],
-    /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
-    /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
+    /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior
+    /// is unspecified and platform dependent, including the possibility that it will deadlock.
+    /// However, if this method returns, then a shared lock is held.
     ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
@@ -696,9 +700,13 @@ impl File {
     /// and the `LockFileEx` function on Windows. Note that, this
     /// [may change in the future][changes].
     ///
+    /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,
+    /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.
+    ///
     /// [changes]: io#platform-specific-behavior
     ///
     /// [`lock`]: File::lock
+    /// [`lock_shared`]: File::lock_shared
     /// [`try_lock`]: File::try_lock
     /// [`try_lock_shared`]: File::try_lock_shared
     /// [`unlock`]: File::unlock
@@ -708,7 +716,6 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -717,29 +724,28 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "file_lock", issue = "130994")]
+    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
     pub fn lock_shared(&self) -> io::Result<()> {
         self.inner.lock_shared()
     }
 
-    /// Try to acquire an exclusive advisory lock on the file.
+    /// Try to acquire an exclusive lock on the file.
     ///
     /// Returns `Ok(false)` if a different lock is already held on this file (via another
     /// handle/descriptor).
     ///
-    /// This acquires an exclusive advisory lock; no other file handle to this file may acquire
-    /// another lock.
+    /// This acquires an exclusive lock; no other file handle to this file may acquire another lock.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact
-    /// behavior is unspecified and platform dependent, including the possibility that it will
-    /// deadlock. However, if this method returns `Ok(true)`, then it has acquired an exclusive
-    /// lock.
+    /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
+    /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
+    /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
+    /// cause non-lockholders to block.
     ///
-    /// If the file not open for writing, it is unspecified whether this function returns an error.
+    /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior
+    /// is unspecified and platform dependent, including the possibility that it will deadlock.
+    /// However, if this method returns `Ok(true)`, then it has acquired an exclusive lock.
     ///
-    /// Note, this is an advisory lock meant to interact with [`lock`], [`lock_shared`],
-    /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
-    /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
+    /// If the file not open for writing, it is unspecified whether this function returns an error.
     ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
@@ -751,10 +757,14 @@ impl File {
     /// and `LOCKFILE_FAIL_IMMEDIATELY` flags. Note that, this
     /// [may change in the future][changes].
     ///
+    /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,
+    /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.
+    ///
     /// [changes]: io#platform-specific-behavior
     ///
     /// [`lock`]: File::lock
     /// [`lock_shared`]: File::lock_shared
+    /// [`try_lock`]: File::try_lock
     /// [`try_lock_shared`]: File::try_lock_shared
     /// [`unlock`]: File::unlock
     /// [`read`]: Read::read
@@ -763,7 +773,6 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -772,27 +781,28 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "file_lock", issue = "130994")]
+    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
     pub fn try_lock(&self) -> io::Result<bool> {
         self.inner.try_lock()
     }
 
-    /// Try to acquire a shared (non-exclusive) advisory lock on the file.
+    /// Try to acquire a shared (non-exclusive) lock on the file.
     ///
     /// Returns `Ok(false)` if an exclusive lock is already held on this file (via another
     /// handle/descriptor).
     ///
-    /// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but
-    /// none may hold an exclusive lock at the same time.
+    /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may
+    /// hold an exclusive lock at the same time.
     ///
-    /// If this file handle, or a clone of it, already holds an advisory lock, the exact behavior is
+    /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
+    /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
+    /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
+    /// cause non-lockholders to block.
+    ///
+    /// If this file handle, or a clone of it, already holds an lock, the exact behavior is
     /// unspecified and platform dependent, including the possibility that it will deadlock.
     /// However, if this method returns `Ok(true)`, then it has acquired a shared lock.
     ///
-    /// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`],
-    /// [`try_lock`], and [`unlock`]. Its interactions with other methods, such as [`read`]
-    /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
-    ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
     ///
@@ -803,11 +813,15 @@ impl File {
     /// `LOCKFILE_FAIL_IMMEDIATELY` flag. Note that, this
     /// [may change in the future][changes].
     ///
+    /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,
+    /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.
+    ///
     /// [changes]: io#platform-specific-behavior
     ///
     /// [`lock`]: File::lock
     /// [`lock_shared`]: File::lock_shared
     /// [`try_lock`]: File::try_lock
+    /// [`try_lock_shared`]: File::try_lock_shared
     /// [`unlock`]: File::unlock
     /// [`read`]: Read::read
     /// [`write`]: Write::write
@@ -815,7 +829,6 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -824,7 +837,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "file_lock", issue = "130994")]
+    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
     pub fn try_lock_shared(&self) -> io::Result<bool> {
         self.inner.try_lock_shared()
     }
@@ -844,12 +857,14 @@ impl File {
     /// and the `UnlockFile` function on Windows. Note that, this
     /// [may change in the future][changes].
     ///
+    /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,
+    /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.
+    ///
     /// [changes]: io#platform-specific-behavior
     ///
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -859,7 +874,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "file_lock", issue = "130994")]
+    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
     pub fn unlock(&self) -> io::Result<()> {
         self.inner.unlock()
     }
@@ -2511,6 +2526,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// * `from` does not exist.
 /// * The current process does not have the permission rights to read
 ///   `from` or write `to`.
+/// * The parent directory of `to` doesn't exist.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 8e307f57cf9..1a266f71965 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,5 +1,6 @@
 use rand::RngCore;
 
+use crate::char::MAX_LEN_UTF8;
 use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::prelude::*;
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
@@ -155,7 +156,7 @@ fn file_test_io_non_positional_read() {
 #[test]
 fn file_test_io_seek_and_tell_smoke_test() {
     let message = "ten-four";
-    let mut read_mem = [0; 4];
+    let mut read_mem = [0; MAX_LEN_UTF8];
     let set_cursor = 4 as u64;
     let tell_pos_pre_read;
     let tell_pos_post_read;
@@ -356,7 +357,7 @@ fn file_test_io_seek_shakedown() {
     let chunk_one: &str = "qwer";
     let chunk_two: &str = "asdf";
     let chunk_three: &str = "zxcv";
-    let mut read_mem = [0; 4];
+    let mut read_mem = [0; MAX_LEN_UTF8];
     let tmpdir = tmpdir();
     let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
     {
@@ -621,7 +622,7 @@ fn file_test_directoryinfo_readdir() {
         check!(w.write(msg));
     }
     let files = check!(fs::read_dir(dir));
-    let mut mem = [0; 4];
+    let mut mem = [0; MAX_LEN_UTF8];
     for f in files {
         let f = f.unwrap().path();
         {
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 318c3508221..661c422811a 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -239,6 +239,7 @@ fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Re
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Stdin")]
 pub struct Stdin {
     inner: &'static Mutex<BufReader<StdinRaw>>,
 }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 750116c6269..0661b3d770e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -284,6 +284,7 @@
 #![feature(cfg_sanitizer_cfi)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfi_encoding)]
+#![feature(char_max_len)]
 #![feature(concat_idents)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs
index 42aada131da..34f0e89f2f1 100644
--- a/library/std/src/os/wasi/fs.rs
+++ b/library/std/src/os/wasi/fs.rs
@@ -162,13 +162,6 @@ pub trait FileExt {
         Ok(())
     }
 
-    /// Returns the current position within the file.
-    ///
-    /// This corresponds to the `fd_tell` syscall and is similar to
-    /// `seek` where you offset 0 bytes from the current position.
-    #[doc(alias = "fd_tell")]
-    fn tell(&self) -> io::Result<u64>;
-
     /// Adjusts the flags associated with this file.
     ///
     /// This corresponds to the `fd_fdstat_set_flags` syscall.
@@ -240,10 +233,6 @@ impl FileExt for fs::File {
         self.as_inner().as_inner().pwrite(bufs, offset)
     }
 
-    fn tell(&self) -> io::Result<u64> {
-        self.as_inner().as_inner().tell()
-    }
-
     fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> {
         self.as_inner().as_inner().set_flags(flags)
     }
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 61801db072a..22776ae2bc4 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -255,6 +255,7 @@ pub use crate::panicking::{set_hook, take_hook};
 #[stable(feature = "panic_any", since = "1.51.0")]
 #[inline]
 #[track_caller]
+#[cfg_attr(not(test), rustc_diagnostic_item = "panic_any")]
 pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
     crate::panicking::begin_panic(msg);
 }
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index fd0fd1cb755..bdd4844b651 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -217,6 +217,7 @@ use crate::{fmt, fs, str};
 ///
 /// [`wait`]: Child::wait
 #[stable(feature = "process", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Child")]
 pub struct Child {
     pub(crate) handle: imp::Process,
 
@@ -2115,6 +2116,7 @@ impl Child {
     /// [`ErrorKind`]: io::ErrorKind
     /// [`InvalidInput`]: io::ErrorKind::InvalidInput
     #[stable(feature = "process", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "child_kill")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
     }
@@ -2135,6 +2137,7 @@ impl Child {
     /// ```
     #[must_use]
     #[stable(feature = "process_id", since = "1.3.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "child_id")]
     pub fn id(&self) -> u32 {
         self.handle.id()
     }
@@ -2375,6 +2378,7 @@ pub fn exit(code: i32) -> ! {
 /// [panic hook]: crate::panic::set_hook
 #[stable(feature = "process_abort", since = "1.17.0")]
 #[cold]
+#[cfg_attr(not(test), rustc_diagnostic_item = "process_abort")]
 pub fn abort() -> ! {
     crate::sys::abort_internal();
 }
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 5b65d862be1..1d337694944 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -8,7 +8,7 @@ use crate::collections::TryReserveError;
 use crate::fmt::Write;
 use crate::rc::Rc;
 use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, mem, str};
 
 #[cfg(test)]
@@ -25,6 +25,37 @@ pub struct Slice {
     pub inner: [u8],
 }
 
+impl IntoInner<Vec<u8>> for Buf {
+    fn into_inner(self) -> Vec<u8> {
+        self.inner
+    }
+}
+
+impl FromInner<Vec<u8>> for Buf {
+    fn from_inner(inner: Vec<u8>) -> Self {
+        Buf { inner }
+    }
+}
+
+impl AsInner<[u8]> for Buf {
+    #[inline]
+    fn as_inner(&self) -> &[u8] {
+        &self.inner
+    }
+}
+
+impl fmt::Debug for Buf {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), f)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), f)
+    }
+}
+
 impl fmt::Debug for Slice {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner.utf8_chunks().debug(), f)
@@ -55,18 +86,6 @@ impl fmt::Display for Slice {
     }
 }
 
-impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
-    }
-}
-
 impl Clone for Buf {
     #[inline]
     fn clone(&self) -> Self {
@@ -79,19 +98,6 @@ impl Clone for Buf {
     }
 }
 
-impl IntoInner<Vec<u8>> for Buf {
-    fn into_inner(self) -> Vec<u8> {
-        self.inner
-    }
-}
-
-impl AsInner<[u8]> for Buf {
-    #[inline]
-    fn as_inner(&self) -> &[u8] {
-        &self.inner
-    }
-}
-
 impl Buf {
     #[inline]
     pub fn into_encoded_bytes(self) -> Vec<u8> {
@@ -103,6 +109,12 @@ impl Buf {
         Self { inner: s }
     }
 
+    #[inline]
+    pub fn into_string(self) -> Result<String, Buf> {
+        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
+    }
+
+    #[inline]
     pub fn from_string(s: String) -> Buf {
         Buf { inner: s.into_bytes() }
     }
@@ -123,6 +135,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn push_slice(&mut self, s: &Slice) {
+        self.inner.extend_from_slice(&s.inner)
+    }
+
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
     }
@@ -157,7 +174,7 @@ impl Buf {
         // SAFETY: Slice just wraps [u8],
         // and &*self.inner is &[u8], therefore
         // transmuting &[u8] to &Slice is safe.
-        unsafe { mem::transmute(&*self.inner) }
+        unsafe { mem::transmute(self.inner.as_slice()) }
     }
 
     #[inline]
@@ -165,15 +182,7 @@ impl Buf {
         // SAFETY: Slice just wraps [u8],
         // and &mut *self.inner is &mut [u8], therefore
         // transmuting &mut [u8] to &mut Slice is safe.
-        unsafe { mem::transmute(&mut *self.inner) }
-    }
-
-    pub fn into_string(self) -> Result<String, Buf> {
-        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
-    }
-
-    pub fn push_slice(&mut self, s: &Slice) {
-        self.inner.extend_from_slice(&s.inner)
+        unsafe { mem::transmute(self.inner.as_mut_slice()) }
     }
 
     #[inline]
@@ -278,18 +287,22 @@ impl Slice {
         unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) }
     }
 
+    #[inline]
     pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
         str::from_utf8(&self.inner)
     }
 
+    #[inline]
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
         String::from_utf8_lossy(&self.inner)
     }
 
+    #[inline]
     pub fn to_owned(&self) -> Buf {
         Buf { inner: self.inner.to_vec() }
     }
 
+    #[inline]
     pub fn clone_into(&self, buf: &mut Buf) {
         self.inner.clone_into(&mut buf.inner)
     }
@@ -300,6 +313,7 @@ impl Slice {
         unsafe { mem::transmute(boxed) }
     }
 
+    #[inline]
     pub fn empty_box() -> Box<Slice> {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index a4ad5966afe..19728d33990 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -10,11 +10,16 @@ use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, mem};
 
-#[derive(Clone, Hash)]
+#[derive(Hash)]
 pub struct Buf {
     pub inner: Wtf8Buf,
 }
 
+#[repr(transparent)]
+pub struct Slice {
+    pub inner: Wtf8,
+}
+
 impl IntoInner<Wtf8Buf> for Buf {
     fn into_inner(self) -> Wtf8Buf {
         self.inner
@@ -35,31 +40,38 @@ impl AsInner<Wtf8> for Buf {
 }
 
 impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), f)
     }
 }
 
 impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), f)
     }
 }
 
-#[repr(transparent)]
-pub struct Slice {
-    pub inner: Wtf8,
-}
-
 impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.inner, formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.inner, f)
     }
 }
 
 impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.inner, formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.inner, f)
+    }
+}
+
+impl Clone for Buf {
+    #[inline]
+    fn clone(&self) -> Self {
+        Buf { inner: self.inner.clone() }
+    }
+
+    #[inline]
+    fn clone_from(&mut self, source: &Self) {
+        self.inner.clone_from(&source.inner)
     }
 }
 
@@ -74,62 +86,57 @@ impl Buf {
         unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
     }
 
-    pub fn with_capacity(capacity: usize) -> Buf {
-        Buf { inner: Wtf8Buf::with_capacity(capacity) }
-    }
-
-    pub fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    pub fn capacity(&self) -> usize {
-        self.inner.capacity()
+    #[inline]
+    pub fn into_string(self) -> Result<String, Buf> {
+        self.inner.into_string().map_err(|buf| Buf { inner: buf })
     }
 
+    #[inline]
     pub fn from_string(s: String) -> Buf {
         Buf { inner: Wtf8Buf::from_string(s) }
     }
 
-    pub fn as_slice(&self) -> &Slice {
-        // SAFETY: Slice is just a wrapper for Wtf8,
-        // and self.inner.as_slice() returns &Wtf8.
-        // Therefore, transmuting &Wtf8 to &Slice is safe.
-        unsafe { mem::transmute(self.inner.as_slice()) }
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf { inner: Wtf8Buf::with_capacity(capacity) }
     }
 
-    pub fn as_mut_slice(&mut self) -> &mut Slice {
-        // SAFETY: Slice is just a wrapper for Wtf8,
-        // and self.inner.as_mut_slice() returns &mut Wtf8.
-        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
-        // Additionally, care should be taken to ensure the slice
-        // is always valid Wtf8.
-        unsafe { mem::transmute(self.inner.as_mut_slice()) }
+    #[inline]
+    pub fn clear(&mut self) {
+        self.inner.clear()
     }
 
-    pub fn into_string(self) -> Result<String, Buf> {
-        self.inner.into_string().map_err(|buf| Buf { inner: buf })
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
     }
 
+    #[inline]
     pub fn push_slice(&mut self, s: &Slice) {
         self.inner.push_wtf8(&s.inner)
     }
 
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
     }
 
+    #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.inner.try_reserve(additional)
     }
 
+    #[inline]
     pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    #[inline]
     pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.inner.try_reserve_exact(additional)
     }
 
+    #[inline]
     pub fn shrink_to_fit(&mut self) {
         self.inner.shrink_to_fit()
     }
@@ -140,6 +147,24 @@ impl Buf {
     }
 
     #[inline]
+    pub fn as_slice(&self) -> &Slice {
+        // SAFETY: Slice is just a wrapper for Wtf8,
+        // and self.inner.as_slice() returns &Wtf8.
+        // Therefore, transmuting &Wtf8 to &Slice is safe.
+        unsafe { mem::transmute(self.inner.as_slice()) }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut Slice {
+        // SAFETY: Slice is just a wrapper for Wtf8,
+        // and self.inner.as_mut_slice() returns &mut Wtf8.
+        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
+        // Additionally, care should be taken to ensure the slice
+        // is always valid Wtf8.
+        unsafe { mem::transmute(self.inner.as_mut_slice()) }
+    }
+
+    #[inline]
     pub fn leak<'a>(self) -> &'a mut Slice {
         unsafe { mem::transmute(self.inner.leak()) }
     }
@@ -194,6 +219,7 @@ impl Slice {
     }
 
     #[track_caller]
+    #[inline]
     pub fn check_public_boundary(&self, index: usize) {
         check_utf8_boundary(&self.inner, index);
     }
@@ -203,18 +229,22 @@ impl Slice {
         unsafe { mem::transmute(Wtf8::from_str(s)) }
     }
 
+    #[inline]
     pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
         self.inner.as_str()
     }
 
+    #[inline]
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
         self.inner.to_string_lossy()
     }
 
+    #[inline]
     pub fn to_owned(&self) -> Buf {
         Buf { inner: self.inner.to_owned() }
     }
 
+    #[inline]
     pub fn clone_into(&self, buf: &mut Buf) {
         self.inner.clone_into(&mut buf.inner)
     }
@@ -224,6 +254,7 @@ impl Slice {
         unsafe { mem::transmute(self.inner.into_box()) }
     }
 
+    #[inline]
     pub fn empty_box() -> Box<Slice> {
         unsafe { mem::transmute(Wtf8::empty_box()) }
     }
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index 8dc61edb603..4fbdc839939 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -204,7 +204,7 @@ compat_fn_with_fallback! {
     pub fn NtReleaseKeyedEvent(
         EventHandle: HANDLE,
         Key: *const c_void,
-        Alertable: BOOLEAN,
+        Alertable: bool,
         Timeout: *mut i64
     ) -> NTSTATUS {
         panic!("keyed events not available")
@@ -213,7 +213,7 @@ compat_fn_with_fallback! {
     pub fn NtWaitForKeyedEvent(
         EventHandle: HANDLE,
         Key: *const c_void,
-        Alertable: BOOLEAN,
+        Alertable: bool,
         Timeout: *mut i64
     ) -> NTSTATUS {
         panic!("keyed events not available")
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index fd3f559ba19..1b245991aa7 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -1,5 +1,6 @@
 #![unstable(issue = "none", feature = "windows_stdio")]
 
+use core::char::MAX_LEN_UTF8;
 use core::str::utf8_char_width;
 
 use super::api::{self, WinError};
@@ -426,7 +427,7 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
 
 impl IncompleteUtf8 {
     pub const fn new() -> IncompleteUtf8 {
-        IncompleteUtf8 { bytes: [0; 4], len: 0 }
+        IncompleteUtf8 { bytes: [0; MAX_LEN_UTF8], len: 0 }
     }
 }
 
diff --git a/library/std/src/sys/random/windows.rs b/library/std/src/sys/random/windows.rs
index 7566000f9e6..f5da637f56c 100644
--- a/library/std/src/sys/random/windows.rs
+++ b/library/std/src/sys/random/windows.rs
@@ -14,7 +14,7 @@ pub fn fill_bytes(mut bytes: &mut [u8]) {
     while !bytes.is_empty() {
         let len = bytes.len().try_into().unwrap_or(u32::MAX);
         let ret = unsafe { c::RtlGenRandom(bytes.as_mut_ptr().cast(), len) };
-        assert_ne!(ret, 0, "failed to generate random data");
+        assert!(ret, "failed to generate random data");
         bytes = &mut bytes[len as usize..];
     }
 }
diff --git a/library/std/src/sys/sync/mutex/windows7.rs b/library/std/src/sys/sync/mutex/windows7.rs
index 689dba10f01..0b57de78ba6 100644
--- a/library/std/src/sys/sync/mutex/windows7.rs
+++ b/library/std/src/sys/sync/mutex/windows7.rs
@@ -44,7 +44,7 @@ impl Mutex {
 
     #[inline]
     pub fn try_lock(&self) -> bool {
-        unsafe { c::TryAcquireSRWLockExclusive(raw(self)) != 0 }
+        unsafe { c::TryAcquireSRWLockExclusive(raw(self)) }
     }
 
     #[inline]
diff --git a/library/std/src/sys/sync/thread_parking/windows7.rs b/library/std/src/sys/sync/thread_parking/windows7.rs
index f7585e882f0..a1a0f8427cd 100644
--- a/library/std/src/sys/sync/thread_parking/windows7.rs
+++ b/library/std/src/sys/sync/thread_parking/windows7.rs
@@ -195,7 +195,7 @@ mod keyed_events {
 
     pub unsafe fn park(parker: Pin<&Parker>) {
         // Wait for unpark() to produce this event.
-        c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut());
+        c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut());
         // Set the state back to EMPTY (from either PARKED or NOTIFIED).
         // Note that we don't just write EMPTY, but use swap() to also
         // include an acquire-ordered read to synchronize with unpark()'s
@@ -218,7 +218,7 @@ mod keyed_events {
 
         // Wait for unpark() to produce this event.
         let unparked =
-            c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS;
+            c::NtWaitForKeyedEvent(handle, parker.ptr(), false, &mut timeout) == c::STATUS_SUCCESS;
 
         // Set the state back to EMPTY (from either PARKED or NOTIFIED).
         let prev_state = parker.state.swap(EMPTY, Acquire);
@@ -228,7 +228,7 @@ mod keyed_events {
             // was set to NOTIFIED, which means we *just* missed an
             // unpark(), which is now blocked on us to wait for it.
             // Wait for it to consume the event and unblock that thread.
-            c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, ptr::null_mut());
+            c::NtWaitForKeyedEvent(handle, parker.ptr(), false, ptr::null_mut());
         }
     }
     pub unsafe fn unpark(parker: Pin<&Parker>) {
@@ -239,7 +239,7 @@ mod keyed_events {
         // To prevent this thread from blocking indefinitely in that case,
         // park_impl() will, after seeing the state set to NOTIFIED after
         // waking up, call NtWaitForKeyedEvent again to unblock us.
-        c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut());
+        c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut());
     }
 
     fn keyed_event_handle() -> c::HANDLE {
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 6c60d901ee9..952c39132b0 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -18,7 +18,7 @@
 #[cfg(test)]
 mod tests;
 
-use core::char::{encode_utf8_raw, encode_utf16_raw};
+use core::char::{MAX_LEN_UTF8, MAX_LEN_UTF16, encode_utf8_raw, encode_utf16_raw};
 use core::clone::CloneToUninit;
 use core::str::next_code_point;
 
@@ -156,9 +156,12 @@ impl ops::DerefMut for Wtf8Buf {
     }
 }
 
-/// Format the string with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+///
+/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
+/// `"a\u{D800}\n"`.
 impl fmt::Debug for Wtf8Buf {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -181,7 +184,7 @@ impl Wtf8Buf {
 
     /// Creates a WTF-8 string from a WTF-8 byte vec.
     ///
-    /// Since the byte vec is not checked for valid WTF-8, this functions is
+    /// Since the byte vec is not checked for valid WTF-8, this function is
     /// marked unsafe.
     #[inline]
     pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
@@ -205,7 +208,7 @@ impl Wtf8Buf {
     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
     #[inline]
     pub fn from_str(s: &str) -> Wtf8Buf {
-        Wtf8Buf { bytes: <[_]>::to_vec(s.as_bytes()), is_known_utf8: true }
+        Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
     }
 
     pub fn clear(&mut self) {
@@ -237,10 +240,11 @@ impl Wtf8Buf {
         string
     }
 
-    /// Copied from String::push
+    /// Appends the given `char` to the end of this string.
     /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
+    /// Copied from String::push.
     fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
-        let mut bytes = [0; 4];
+        let mut bytes = [0; MAX_LEN_UTF8];
         let bytes = encode_utf8_raw(code_point.value, &mut bytes);
         self.bytes.extend_from_slice(bytes)
     }
@@ -264,16 +268,16 @@ impl Wtf8Buf {
     ///
     /// # Panics
     ///
-    /// Panics if the new capacity overflows `usize`.
+    /// Panics if the new capacity exceeds `isize::MAX` bytes.
     #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.bytes.reserve(additional)
     }
 
-    /// Tries to reserve capacity for at least `additional` more length units
-    /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid
-    /// frequent reallocations. After calling `try_reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// Tries to reserve capacity for at least `additional` more bytes to be
+    /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
+    /// avoid frequent reallocations. After calling `try_reserve`, capacity will
+    /// be greater than or equal to `self.len() + additional`. Does nothing if
     /// capacity is already sufficient. This method preserves the contents even
     /// if an error occurs.
     ///
@@ -291,8 +295,8 @@ impl Wtf8Buf {
         self.bytes.reserve_exact(additional)
     }
 
-    /// Tries to reserve the minimum capacity for exactly `additional`
-    /// length units in the given `Wtf8Buf`. After calling
+    /// Tries to reserve the minimum capacity for exactly `additional` more
+    /// bytes to be inserted in the given `Wtf8Buf`. After calling
     /// `try_reserve_exact`, capacity will be greater than or equal to
     /// `self.len() + additional` if it returns `Ok(())`.
     /// Does nothing if the capacity is already sufficient.
@@ -440,22 +444,17 @@ impl Wtf8Buf {
     ///
     /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
     pub fn into_string_lossy(mut self) -> String {
-        // Fast path: If we already have UTF-8, we can return it immediately.
-        if self.is_known_utf8 {
-            return unsafe { String::from_utf8_unchecked(self.bytes) };
-        }
-
-        let mut pos = 0;
-        loop {
-            match self.next_surrogate(pos) {
-                Some((surrogate_pos, _)) => {
-                    pos = surrogate_pos + 3;
-                    self.bytes[surrogate_pos..pos]
-                        .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
-                }
-                None => return unsafe { String::from_utf8_unchecked(self.bytes) },
+        if !self.is_known_utf8 {
+            let mut pos = 0;
+            while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
+                pos = surrogate_pos + 3;
+                // Surrogates and the replacement character are all 3 bytes, so
+                // they can substituted in-place.
+                self.bytes[surrogate_pos..pos]
+                    .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
             }
         }
+        unsafe { String::from_utf8_unchecked(self.bytes) }
     }
 
     /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
@@ -535,9 +534,9 @@ impl AsInner<[u8]> for Wtf8 {
     }
 }
 
-/// Format the slice with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
 impl fmt::Debug for Wtf8 {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
@@ -562,6 +561,8 @@ impl fmt::Debug for Wtf8 {
     }
 }
 
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
 impl fmt::Display for Wtf8 {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         let wtf8_bytes = &self.bytes;
@@ -672,9 +673,8 @@ impl Wtf8 {
     ///
     /// This only copies the data if necessary (if it contains any surrogate).
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
-        let surrogate_pos = match self.next_surrogate(0) {
-            None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }),
-            Some((pos, _)) => pos,
+        let Some((surrogate_pos, _)) = self.next_surrogate(0) else {
+            return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) });
         };
         let wtf8_bytes = &self.bytes;
         let mut utf8_bytes = Vec::with_capacity(self.len());
@@ -964,7 +964,7 @@ pub struct Wtf8CodePoints<'a> {
     bytes: slice::Iter<'a, u8>,
 }
 
-impl<'a> Iterator for Wtf8CodePoints<'a> {
+impl Iterator for Wtf8CodePoints<'_> {
     type Item = CodePoint;
 
     #[inline]
@@ -990,7 +990,7 @@ pub struct EncodeWide<'a> {
 
 // Copied from libunicode/u_str.rs
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for EncodeWide<'a> {
+impl Iterator for EncodeWide<'_> {
     type Item = u16;
 
     #[inline]
@@ -1001,7 +1001,7 @@ impl<'a> Iterator for EncodeWide<'a> {
             return Some(tmp);
         }
 
-        let mut buf = [0; 2];
+        let mut buf = [0; MAX_LEN_UTF16];
         self.code_points.next().map(|code_point| {
             let n = encode_utf16_raw(code_point.value, &mut buf).len();
             if n == 2 {
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 88b3e9e0ceb..5ab71413586 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -93,11 +93,17 @@ use crate::sys_common::{FromInner, IntoInner};
 /// use std::time::{Instant, Duration};
 ///
 /// let now = Instant::now();
-/// let max_seconds = u64::MAX / 1_000_000_000;
-/// let duration = Duration::new(max_seconds, 0);
+/// let days_per_10_millennia = 365_2425;
+/// let solar_seconds_per_day = 60 * 60 * 24;
+/// let millenium_in_solar_seconds = 31_556_952_000;
+/// assert_eq!(millenium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10);
+///
+/// let duration = Duration::new(millenium_in_solar_seconds, 0);
 /// println!("{:?}", now + duration);
 /// ```
 ///
+/// For cross-platform code, you can comfortably use durations of up to around one hundred years.
+///
 /// # Underlying System calls
 ///
 /// The following system calls are [currently] being used by `now()` to find out
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index fbd0dc3ec30..f25dfaab0f1 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -523,19 +523,31 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
 /// Handles editor-specific setup differences
 #[derive(Clone, Debug, Eq, PartialEq)]
 enum EditorKind {
-    Vscode,
-    Vim,
     Emacs,
     Helix,
+    Vim,
+    VsCode,
+    Zed,
 }
 
 impl EditorKind {
+    // Used in `./tests.rs`.
+    #[allow(dead_code)]
+    pub const ALL: &[EditorKind] = &[
+        EditorKind::Emacs,
+        EditorKind::Helix,
+        EditorKind::Vim,
+        EditorKind::VsCode,
+        EditorKind::Zed,
+    ];
+
     fn prompt_user() -> io::Result<Option<EditorKind>> {
         let prompt_str = "Available editors:
-1. vscode
-2. vim
-3. emacs
-4. helix
+1. Emacs
+2. Helix
+3. Vim
+4. VS Code
+5. Zed
 
 Select which editor you would like to set up [default: None]: ";
 
@@ -543,28 +555,41 @@ Select which editor you would like to set up [default: None]: ";
         loop {
             print!("{}", prompt_str);
             io::stdout().flush()?;
-            input.clear();
             io::stdin().read_line(&mut input)?;
-            match input.trim().to_lowercase().as_str() {
-                "1" | "vscode" => return Ok(Some(EditorKind::Vscode)),
-                "2" | "vim" => return Ok(Some(EditorKind::Vim)),
-                "3" | "emacs" => return Ok(Some(EditorKind::Emacs)),
-                "4" | "helix" => return Ok(Some(EditorKind::Helix)),
-                "" => return Ok(None),
+
+            let mut modified_input = input.to_lowercase();
+            modified_input.retain(|ch| !ch.is_whitespace());
+            match modified_input.as_str() {
+                "1" | "emacs" => return Ok(Some(EditorKind::Emacs)),
+                "2" | "helix" => return Ok(Some(EditorKind::Helix)),
+                "3" | "vim" => return Ok(Some(EditorKind::Vim)),
+                "4" | "vscode" => return Ok(Some(EditorKind::VsCode)),
+                "5" | "zed" => return Ok(Some(EditorKind::Zed)),
+                "" | "none" => return Ok(None),
                 _ => {
                     eprintln!("ERROR: unrecognized option '{}'", input.trim());
                     eprintln!("NOTE: press Ctrl+C to exit");
                 }
-            };
+            }
+
+            input.clear();
         }
     }
 
     /// A list of historical hashes of each LSP settings file
     /// New entries should be appended whenever this is updated so we can detect
     /// outdated vs. user-modified settings files.
-    fn hashes(&self) -> Vec<&str> {
+    fn hashes(&self) -> &'static [&'static str] {
         match self {
-            EditorKind::Vscode | EditorKind::Vim => vec![
+            EditorKind::Emacs => &[
+                "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
+                "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
+            ],
+            EditorKind::Helix => &[
+                "2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
+                "6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040",
+            ],
+            EditorKind::Vim | EditorKind::VsCode => &[
                 "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
                 "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
                 "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
@@ -576,12 +601,8 @@ Select which editor you would like to set up [default: None]: ";
                 "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
                 "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
             ],
-            EditorKind::Emacs => vec![
-                "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
-                "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
-            ],
-            EditorKind::Helix => {
-                vec!["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"]
+            EditorKind::Zed => {
+                &["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"]
             }
         }
     }
@@ -592,29 +613,31 @@ Select which editor you would like to set up [default: None]: ";
 
     fn settings_short_path(&self) -> PathBuf {
         self.settings_folder().join(match self {
-            EditorKind::Vscode => "settings.json",
-            EditorKind::Vim => "coc-settings.json",
             EditorKind::Emacs => ".dir-locals.el",
             EditorKind::Helix => "languages.toml",
+            EditorKind::Vim => "coc-settings.json",
+            EditorKind::VsCode | EditorKind::Zed => "settings.json",
         })
     }
 
     fn settings_folder(&self) -> PathBuf {
         match self {
-            EditorKind::Vscode => PathBuf::from(".vscode"),
-            EditorKind::Vim => PathBuf::from(".vim"),
             EditorKind::Emacs => PathBuf::new(),
             EditorKind::Helix => PathBuf::from(".helix"),
+            EditorKind::Vim => PathBuf::from(".vim"),
+            EditorKind::VsCode => PathBuf::from(".vscode"),
+            EditorKind::Zed => PathBuf::from(".zed"),
         }
     }
 
-    fn settings_template(&self) -> &str {
+    fn settings_template(&self) -> &'static str {
         match self {
-            EditorKind::Vscode | EditorKind::Vim => {
-                include_str!("../../../../etc/rust_analyzer_settings.json")
-            }
             EditorKind::Emacs => include_str!("../../../../etc/rust_analyzer_eglot.el"),
             EditorKind::Helix => include_str!("../../../../etc/rust_analyzer_helix.toml"),
+            EditorKind::Vim | EditorKind::VsCode => {
+                include_str!("../../../../etc/rust_analyzer_settings.json")
+            }
+            EditorKind::Zed => include_str!("../../../../etc/rust_analyzer_zed.json"),
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/setup/tests.rs b/src/bootstrap/src/core/build_steps/setup/tests.rs
index f3d4b6aa4db..e8f83ff75e4 100644
--- a/src/bootstrap/src/core/build_steps/setup/tests.rs
+++ b/src/bootstrap/src/core/build_steps/setup/tests.rs
@@ -5,13 +5,16 @@ use crate::utils::helpers::hex_encode;
 
 #[test]
 fn check_matching_settings_hash() {
-    let editor = EditorKind::Vscode;
-    let mut hasher = sha2::Sha256::new();
-    hasher.update(&editor.settings_template());
-    let hash = hex_encode(hasher.finalize().as_slice());
-    assert_eq!(
-        &hash,
-        editor.hashes().last().unwrap(),
-        "Update `EditorKind::hashes()` with the new hash of `src/etc/rust_analyzer_settings.json`"
-    );
+    for editor in EditorKind::ALL {
+        let mut hasher = sha2::Sha256::new();
+        hasher.update(&editor.settings_template());
+        let hash = hex_encode(hasher.finalize().as_slice());
+        assert_eq!(
+            &hash,
+            editor.hashes().last().unwrap(),
+            "Update `EditorKind::hashes()` with the new hash of `{}` for `EditorKind::{:?}`",
+            editor.settings_template(),
+            editor,
+        );
+    }
 }
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
index dbfd6f47dc6..34bf6bb7013 100644
--- a/src/bootstrap/src/utils/proc_macro_deps.rs
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -6,25 +6,18 @@ pub static CRATES: &[&str] = &[
     "annotate-snippets",
     "anstyle",
     "basic-toml",
-    "block-buffer",
     "bumpalo",
-    "cfg-if",
-    "cpufeatures",
-    "crypto-common",
     "darling",
     "darling_core",
     "derive_builder_core",
-    "digest",
     "fluent-bundle",
     "fluent-langneg",
     "fluent-syntax",
     "fnv",
-    "generic-array",
     "heck",
     "ident_case",
     "intl-memoizer",
     "intl_pluralrules",
-    "libc",
     "log",
     "memchr",
     "mime",
@@ -32,17 +25,12 @@ pub static CRATES: &[&str] = &[
     "minimal-lexical",
     "nom",
     "num-conv",
-    "once_cell",
-    "pest",
-    "pest_generator",
-    "pest_meta",
     "proc-macro2",
     "quote",
     "rinja_parser",
     "rustc-hash",
     "self_cell",
     "serde",
-    "sha2",
     "smallvec",
     "stable_deref_trait",
     "strsim",
@@ -52,15 +40,12 @@ pub static CRATES: &[&str] = &[
     "time-core",
     "tinystr",
     "type-map",
-    "typenum",
-    "ucd-trie",
     "unic-langid",
     "unic-langid-impl",
     "unic-langid-macros",
     "unicase",
     "unicode-ident",
     "unicode-width",
-    "version_check",
     "wasm-bindgen-backend",
     "wasm-bindgen-macro-support",
     "wasm-bindgen-shared",
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index d2697ac27ab..6658b83efc8 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -236,9 +236,15 @@ args=
 if [ "$SCCACHE_BUCKET" != "" ]; then
     args="$args --env SCCACHE_BUCKET"
     args="$args --env SCCACHE_REGION"
-    args="$args --env AWS_ACCESS_KEY_ID"
-    args="$args --env AWS_SECRET_ACCESS_KEY"
     args="$args --env AWS_REGION"
+
+    # Disable S3 authentication for PR builds, because the access keys are missing
+    if [ "$PR_CI_JOB" != "" ]; then
+      args="$args --env SCCACHE_S3_NO_CREDENTIALS=1"
+    else
+      args="$args --env AWS_ACCESS_KEY_ID"
+      args="$args --env AWS_SECRET_ACCESS_KEY"
+    fi
 else
     mkdir -p $HOME/.cache/sccache
     args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache"
diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh
index 6c713e1f861..f66671c64d2 100644
--- a/src/ci/docker/scripts/sccache.sh
+++ b/src/ci/docker/scripts/sccache.sh
@@ -6,10 +6,10 @@ set -ex
 
 case "$(uname -m)" in
     x86_64)
-        url="https://ci-mirrors.rust-lang.org/rustc/2021-08-24-sccache-v0.2.15-x86_64-unknown-linux-musl"
+        url="https://ci-mirrors.rust-lang.org/rustc/2025-01-07-sccache-v0.9.1-x86_64-unknown-linux-musl"
         ;;
     aarch64)
-        url="https://ci-mirrors.rust-lang.org/rustc/2021-08-25-sccache-v0.2.15-aarch64-unknown-linux-musl"
+        url="https://ci-mirrors.rust-lang.org/rustc/2025-01-07-sccache-v0.9.1-aarch64-unknown-linux-musl"
         ;;
     *)
         echo "unsupported architecture: $(uname -m)"
diff --git a/src/ci/run.sh b/src/ci/run.sh
index b874f71832d..536754f12bc 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -279,5 +279,5 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
 fi
 
 echo "::group::sccache stats"
-sccache --show-stats || true
+sccache --show-adv-stats || true
 echo "::endgroup::"
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index 91eab2e7a08..c8c501e646a 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -32,6 +32,12 @@ if isWindows && isKnownToBeMingwBuild; then
             ;;
     esac
 
+    # Stop /msys64/bin from being prepended to PATH by adding the bin directory manually.
+    # Note that this intentionally uses a Windows style path instead of the msys2 path to
+    # avoid being auto-translated into `/usr/bin`, which will not have the desired effect.
+    msys2Path="c:/msys64"
+    ciCommandAddPath "${msys2Path}/usr/bin"
+
     mingw_dir="mingw${bits}"
 
     curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index 2c6c3fe1df8..5c041d6cb70 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -154,6 +154,16 @@ You can run `./x setup editor` and select `helix`, which will prompt you to
 create `languages.toml` with the recommended configuration for Helix. The
 recommended settings live at [`src/etc/rust_analyzer_helix.toml`].
 
+### Zed
+
+Zed comes with built-in LSP and rust-analyzer support.
+It can be configured through `.zed/settings.json`, as described
+[here](https://zed.dev/docs/configuring-languages). Selecting `zed`
+in `./x setup editor` will prompt you to create a `.zed/settings.json`
+file which will configure Zed with the recommended configuration. The
+recommended `rust-analyzer` settings live
+at [`src/etc/rust_analyzer_zed.json`].
+
 ## Check, check, and check again
 
 When doing simple refactoring, it can be useful to run `./x check`
@@ -381,4 +391,5 @@ load this completion.
 [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json
 [`src/etc/rust_analyzer_eglot.el`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_eglot.el
 [`src/etc/rust_analyzer_helix.toml`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_helix.toml
+[`src/etc/rust_analyzer_zed.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_zed.json
 [`src/etc/pre-push.sh`]: https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh
diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md
index 5b67ccd7f4c..fda38ef4fc0 100644
--- a/src/doc/rustc-dev-guide/src/implementing_new_features.md
+++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md
@@ -167,9 +167,7 @@ a new unstable feature:
 
 1. Prevent usage of the new feature unless the feature gate is set.
    You can check it in most places in the compiler using the
-   expression `tcx.features().$feature_name` (or
-   `sess.features_untracked().$feature_name` if the
-   tcx is unavailable)
+   expression `tcx.features().$feature_name()`
 
     If the feature gate is not set, you should either maintain
     the pre-feature behavior or raise an error, depending on
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index b5cd3864620..c4e5c1aac2f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -301,7 +301,7 @@ target | std | host | notes
 [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * |  | Bare Armv8-R, hardfloat
 [`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ |  | ARMv7-A with NuttX
 [`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ |  | ARMv7-A with NuttX, hardfloat
-`avr-unknown-gnu-atmega328` | * |  | AVR. Requires `-Z build-std=core`
+`avr-none` | * |  | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...`
 `bpfeb-unknown-none` | * |  | BPF (big endian)
 `bpfel-unknown-none` | * |  | BPF (little endian)
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux (little endian)
@@ -309,10 +309,10 @@ target | std | host | notes
 [`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux with musl 1.2.3
 [`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX)
 [`i386-apple-ios`](platform-support/apple-ios.md) | ✓ |  | 32-bit x86 iOS (Penryn) [^x86_32-floats-return-ABI]
-[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI]
 [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ |  | 32-bit x86 (original Pentium) [^x86_32-floats-x87]
 [`i586-unknown-redox`](platform-support/redox.md) | ✓ |  | 32-bit x86 Redox OS (PentiumPro) [^x86_32-floats-x87]
 [`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI]
+[`i686-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI]
 `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI]
 [`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI]
 [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI]
diff --git a/src/doc/rustc/src/platform-support/avr-none.md b/src/doc/rustc/src/platform-support/avr-none.md
new file mode 100644
index 00000000000..9c1836222c1
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/avr-none.md
@@ -0,0 +1,81 @@
+# `avr-none`
+
+Series of microcontrollers from Atmel: ATmega8, ATmega328p etc.
+
+**Tier: 3**
+
+## Target maintainers
+
+- [Patryk Wychowaniec](https://github.com/Patryk27) <pwychowaniec@pm.me>
+
+## Requirements
+
+This target is only cross-compiled; x86-64 Linux, x86-64 macOS and aarch64 macOS
+hosts are confirmed to work, but in principle any machine able to run rustc and
+avr-gcc should be good.
+
+Compiling for this target requires `avr-gcc` installed, because a couple of
+intrinsics (like 32-bit multiplication) rely on [`libgcc`](https://github.com/gcc-mirror/gcc/blob/3269a722b7a03613e9c4e2862bc5088c4a17cc11/libgcc/config/avr/lib1funcs.S)
+and can't be provided through `compiler-builtins` yet. This is a limitation that
+[we hope to lift in the future](https://github.com/rust-lang/compiler-builtins/issues/711).
+
+You'll also need to setup the `.cargo/config` file - see below for details.
+
+## Building the target
+
+Rust comes with AVR support enabled, you don't have to rebuild the compiler.
+
+## Building Rust programs
+
+Install `avr-gcc`:
+
+```console
+# Ubuntu:
+$ sudo apt-get install gcc-avr
+
+# Mac:
+$ brew tap osx-cross/avr && brew install avr-gcc
+
+# NixOS (takes a couple of minutes, since it's not provided through Hydra):
+$ nix shell nixpkgs#pkgsCross.avr.buildPackages.gcc11
+```
+
+... setup `.cargo/config` for your project:
+
+```toml
+[build]
+target = "avr-none"
+rustflags = ["-C", "target-cpu=atmega328p"]
+
+[unstable]
+build-std = ["core"]
+```
+
+... and then simply run:
+
+```console
+$ cargo build --release
+```
+
+The final binary will be placed into
+`./target/avr-none/release/your-project.elf`.
+
+Note that since AVRs have rather small amounts of registers, ROM and RAM, it's
+recommended to always use `--release` to avoid running out of space.
+
+Also, please note that specifying `-C target-cpu` is required - here's a list of
+the possible variants:
+
+https://github.com/llvm/llvm-project/blob/093d4db2f3c874d4683fb01194b00dbb20e5c713/clang/lib/Basic/Targets/AVR.cpp#L32
+
+## Testing
+
+You can use [`simavr`](https://github.com/buserror/simavr) to emulate the
+resulting firmware on your machine:
+
+```console
+$ simavr -m atmega328p ./target/avr-none/release/your-project.elf
+```
+
+Alternatively, if you want to write a couple of actual `#[test]`s, you can use
+[`avr-tester`](https://github.com/Patryk27/avr-tester).
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index 339741f1472..77e8caaee4c 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -31,7 +31,7 @@ Currently, the following QNX versions and compilation targets are supported:
 | `aarch64-unknown-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | AArch64             |      ?       |        ✓         |
 | `x86_64-pc-nto-qnx710_iosock`       | QNX Neutrino 7.1 with io-sock | x86_64              |      ?       |        ✓         |
 | `aarch64-unknown-nto-qnx700`        | QNX Neutrino 7.0              | AArch64             |      ?       |        ✓         |
-| `i586-pc-nto-qnx700`                | QNX Neutrino 7.0              | x86                 |              |        ✓         |
+| `i686-pc-nto-qnx700`                | QNX Neutrino 7.0              | x86                 |              |        ✓         |
 
 On QNX Neutrino 7.0 and 7.1, `io-pkt` is used as network stack by default.
 QNX Neutrino 7.1 includes the optional network stack `io-sock`.
diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
index 73264aba858..ba95ab7af6d 100644
--- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
+++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
@@ -129,6 +129,8 @@ As of the time of this writing the proposals that are enabled by default (the
 * `mutable-globals`
 * `reference-types`
 * `sign-ext`
+* `nontrapping-fptoint` (Rust 1.87.0+, LLVM 20+)
+* `bulk-memory` (Rust 1.87.0+, LLVM 20+)
 
 If you're compiling WebAssembly code for an engine that does not support a
 feature in LLVM's default feature set then the feature must be disabled at
diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
index bc587686111..bfdb579cd35 100644
--- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
+++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
 
 This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
 in Rust.
-For more information, see the corresponding typing rules for [Editions 2024 and later].
-On earlier Editions, the current behavior is unspecified.
+For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
+[Editions 2024 and later].
 
 For alternative experimental match ergonomics, see the feature
 [`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md).
 
+[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
 [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
index 43de1849a5e..0c90cec0dbd 100644
--- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
+++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
 
 This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
 in Rust.
-For more information, see the corresponding typing rules for [Editions 2024 and later].
-On earlier Editions, the current behavior is unspecified.
+For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
+[Editions 2024 and later].
 
 For alternative experimental match ergonomics, see the feature
 [`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md).
 
+[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
 [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
diff --git a/src/etc/rust_analyzer_zed.json b/src/etc/rust_analyzer_zed.json
new file mode 100644
index 00000000000..469ea050621
--- /dev/null
+++ b/src/etc/rust_analyzer_zed.json
@@ -0,0 +1,52 @@
+{
+  "lsp": {
+    "rust-analyzer": {
+      "initialization_options": {
+        "cargo": {
+          "buildScripts": {
+            "enable": true,
+            "invocationLocation": "root",
+            "invocationStrategy": "once",
+            "overrideCommand": ["python3", "x.py", "check", "--json-output"]
+          },
+          "extraEnv": {
+            "RUSTC_BOOTSTRAP": "1"
+          },
+          "sysrootSrc": "./library"
+        },
+        "check": {
+          "invocationLocation": "root",
+          "invocationStrategy": "once",
+          "overrideCommand": ["python3", "x.py", "check", "--json-output"]
+        },
+        "linkedProjects": [
+          "Cargo.toml",
+          "library/Cargo.toml",
+          "src/tools/x/Cargo.toml",
+          "src/bootstrap/Cargo.toml",
+          "src/tools/rust-analyzer/Cargo.toml",
+          "compiler/rustc_codegen_cranelift/Cargo.toml",
+          "compiler/rustc_codegen_gcc/Cargo.toml"
+        ],
+        "procMacro": {
+            "enable": true,
+            "server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv"
+        },
+        "rustc": {
+          "source": "./Cargo.toml"
+        },
+        "rustfmt": {
+          "overrideCommand": [
+            "${workspaceFolder}/build/host/rustfmt/bin/rustfmt",
+            "--edition=2021"
+          ]
+        },
+        "server": {
+          "extraEnv": {
+            "RUSTUP_TOOLCHAIN": "nightly"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index c593cdcbcd2..c07cc4dc347 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -13,7 +13,7 @@ rinja = { version = "0.3", default-features = false, features = ["config"] }
 base64 = "0.21.7"
 itertools = "0.12"
 indexmap = "2"
-minifier = { version = "0.3.4", default-features = false }
+minifier = { version = "0.3.5", default-features = false }
 pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false }
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 92ef3ab7a1d..dcc5fd12d81 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1150,9 +1150,9 @@ fn clean_args_from_types_and_body_id<'tcx>(
     Arguments {
         values: types
             .iter()
-            .enumerate()
-            .map(|(i, ty)| Argument {
-                name: name_from_pat(body.params[i].pat),
+            .zip(body.params)
+            .map(|(ty, param)| Argument {
+                name: name_from_pat(param.pat),
                 type_: clean_ty(ty, cx),
                 is_const: false,
             })
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 6b1d1a2fcdd..34656b26ce2 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,5 +1,5 @@
 use std::assert_matches::debug_assert_matches;
-use std::fmt::Write as _;
+use std::fmt::{self, Display, Write as _};
 use std::mem;
 use std::sync::LazyLock as Lazy;
 
@@ -24,6 +24,7 @@ use crate::clean::{
     clean_middle_ty, inline,
 };
 use crate::core::DocContext;
+use crate::display::Joined as _;
 
 #[cfg(test)]
 mod tests;
@@ -250,16 +251,20 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
         hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
     };
 
-    let mut s = String::new();
-    for (i, seg) in segments.iter().enumerate() {
-        if i > 0 {
-            s.push_str("::");
-        }
-        if seg.ident.name != kw::PathRoot {
-            s.push_str(seg.ident.as_str());
-        }
-    }
-    s
+    fmt::from_fn(|f| {
+        segments
+            .iter()
+            .map(|seg| {
+                fmt::from_fn(|f| {
+                    if seg.ident.name != kw::PathRoot {
+                        write!(f, "{}", seg.ident)?;
+                    }
+                    Ok(())
+                })
+            })
+            .joined("::", f)
+    })
+    .to_string()
 }
 
 pub(crate) fn build_deref_target_impls(
@@ -299,35 +304,49 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 
     Symbol::intern(&match p.kind {
         // FIXME(never_patterns): does this make sense?
-        PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => {
+        PatKind::Wild
+        | PatKind::Err(_)
+        | PatKind::Never
+        | PatKind::Struct(..)
+        | PatKind::Range(..) => {
             return kw::Underscore;
         }
         PatKind::Binding(_, _, ident, _) => return ident.name,
+        PatKind::Box(p) | PatKind::Ref(p, _) | PatKind::Guard(p, _) => return name_from_pat(p),
         PatKind::TupleStruct(ref p, ..)
         | PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
         PatKind::Or(pats) => {
-            pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
+            fmt::from_fn(|f| pats.iter().map(|p| name_from_pat(p)).joined(" | ", f)).to_string()
+        }
+        PatKind::Tuple(elts, _) => {
+            format!("({})", fmt::from_fn(|f| elts.iter().map(|p| name_from_pat(p)).joined(", ", f)))
         }
-        PatKind::Tuple(elts, _) => format!(
-            "({})",
-            elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
-        ),
-        PatKind::Box(p) => return name_from_pat(p),
         PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)),
-        PatKind::Ref(p, _) => return name_from_pat(p),
         PatKind::Expr(..) => {
             warn!(
                 "tried to get argument name from PatKind::Expr, which is silly in function arguments"
             );
             return Symbol::intern("()");
         }
-        PatKind::Guard(p, _) => return name_from_pat(p),
-        PatKind::Range(..) => return kw::Underscore,
-        PatKind::Slice(begin, ref mid, end) => {
-            let begin = begin.iter().map(|p| name_from_pat(p).to_string());
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(p).to_string());
-            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
+        PatKind::Slice(begin, mid, end) => {
+            fn print_pat<'a>(pat: &'a Pat<'a>, wild: bool) -> impl Display + 'a {
+                fmt::from_fn(move |f| {
+                    if wild {
+                        f.write_str("..")?;
+                    }
+                    name_from_pat(pat).fmt(f)
+                })
+            }
+
+            format!(
+                "[{}]",
+                fmt::from_fn(|f| {
+                    let begin = begin.iter().map(|p| print_pat(p, false));
+                    let mid = mid.map(|p| print_pat(p, true));
+                    let end = end.iter().map(|p| print_pat(p, false));
+                    begin.chain(mid).chain(end).joined(", ", f)
+                })
+            )
         }
     })
 }
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index d89caabefe3..4792bc525a5 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -1,6 +1,7 @@
 //! Logic for transforming the raw code given by the user into something actually
 //! runnable, e.g. by adding a `main` function if it doesn't already exist.
 
+use std::fmt::{self, Write as _};
 use std::io;
 use std::sync::Arc;
 
@@ -17,6 +18,7 @@ use rustc_span::symbol::sym;
 use tracing::debug;
 
 use super::GlobalTestOptions;
+use crate::display::Joined as _;
 use crate::html::markdown::LangString;
 
 /// This struct contains information about the doctest itself which is then used to generate
@@ -232,13 +234,15 @@ impl DocTestBuilder {
 
             // add extra 4 spaces for each line to offset the code block
             if opts.insert_indent_space {
-                prog.push_str(
-                    &everything_else
+                write!(
+                    prog,
+                    "{}",
+                    fmt::from_fn(|f| everything_else
                         .lines()
-                        .map(|line| format!("    {}", line))
-                        .collect::<Vec<String>>()
-                        .join("\n"),
-                );
+                        .map(|line| fmt::from_fn(move |f| write!(f, "    {line}")))
+                        .joined("\n", f))
+                )
+                .unwrap();
             } else {
                 prog.push_str(everything_else);
             };
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index d2d7415261b..f3201147039 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -2,7 +2,6 @@ use std::cmp::Ordering;
 use std::fmt;
 use std::fmt::Display;
 
-use itertools::Itertools;
 use rinja::Template;
 use rustc_abi::VariantIdx;
 use rustc_data_structures::captures::Captures;
@@ -514,11 +513,7 @@ fn item_module(w: &mut String, cx: &Context<'_>, item: &clean::Item, items: &[cl
                         class = myitem.type_(),
                         unsafety_flag = unsafety_flag,
                         href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
-                        title = [myitem.type_().to_string(), full_path(cx, myitem)]
-                            .iter()
-                            .filter_map(|s| if !s.is_empty() { Some(s.as_str()) } else { None })
-                            .collect::<Vec<_>>()
-                            .join(" "),
+                        title = format_args!("{} {}", myitem.type_(), full_path(cx, myitem)),
                     ),
                 );
             }
@@ -915,7 +910,7 @@ fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                 w,
                 format_args!(
                     "<div class=\"stab must_implement\">At least one of the `{}` methods is required.</div>",
-                    list.iter().join("`, `")
+                    fmt::from_fn(|f| list.iter().joined("`, `", f))
                 ),
             );
         }
@@ -1168,17 +1163,18 @@ fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         js_src_path.extend(cx.current.iter().copied());
         js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
     }
-    let extern_crates = extern_crates
-        .into_iter()
-        .map(|cnum| tcx.crate_name(cnum).to_string())
-        .collect::<Vec<_>>()
-        .join(",");
-    let (extern_before, extern_after) =
-        if extern_crates.is_empty() { ("", "") } else { (" data-ignore-extern-crates=\"", "\"") };
+    let extern_crates = fmt::from_fn(|f| {
+        if !extern_crates.is_empty() {
+            f.write_str(" data-ignore-extern-crates=\"")?;
+            extern_crates.iter().map(|&cnum| tcx.crate_name(cnum)).joined(",", f)?;
+            f.write_str("\"")?;
+        }
+        Ok(())
+    });
     write_str(
         w,
         format_args!(
-            "<script src=\"{src}\"{extern_before}{extern_crates}{extern_after} async></script>",
+            "<script src=\"{src}\"{extern_crates} async></script>",
             src = js_src_path.finish()
         ),
     );
@@ -1400,7 +1396,7 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
             .collect();
         js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
         js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
-        let self_path = self_fqp.iter().map(Symbol::as_str).collect::<Vec<&str>>().join("::");
+        let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
         write_str(
             w,
             format_args!(
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 50c09b98db4..64dbaf9083e 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,4 +1,5 @@
 use std::borrow::Cow;
+use std::cmp::Ordering;
 
 use rinja::Template;
 use rustc_data_structures::fx::FxHashSet;
@@ -12,6 +13,7 @@ use crate::clean;
 use crate::formats::Impl;
 use crate::formats::item_type::ItemType;
 use crate::html::markdown::{IdMap, MarkdownWithToc};
+use crate::html::render::print_item::compare_names;
 
 #[derive(Clone, Copy)]
 pub(crate) enum ModuleLike {
@@ -77,7 +79,7 @@ impl<'a> LinkBlock<'a> {
 }
 
 /// A link to an item. Content should not be escaped.
-#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone)]
+#[derive(Ord, PartialEq, Eq, Hash, Clone)]
 pub(crate) struct Link<'a> {
     /// The content for the anchor tag and title attr
     name: Cow<'a, str>,
@@ -89,6 +91,20 @@ pub(crate) struct Link<'a> {
     children: Vec<Link<'a>>,
 }
 
+impl PartialOrd for Link<'_> {
+    fn partial_cmp(&self, other: &Link<'_>) -> Option<Ordering> {
+        match compare_names(&self.name, &other.name) {
+            Ordering::Equal => (),
+            result => return Some(result),
+        }
+        (&self.name_html, &self.href, &self.children).partial_cmp(&(
+            &other.name_html,
+            &other.href,
+            &other.children,
+        ))
+    }
+}
+
 impl<'a> Link<'a> {
     pub fn new(href: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>) -> Self {
         Self { href: href.into(), name: name.into(), children: vec![], name_html: None }
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 3cb47d8ef91..960b9aa032b 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -94,7 +94,6 @@ impl Finiteness {
 }
 
 impl From<bool> for Finiteness {
-    #[must_use]
     fn from(b: bool) -> Self {
         if b { Infinite } else { Finite }
     }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 4f707e34abf..dd149c4a29b 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -351,21 +351,18 @@ pub enum FullInt {
 }
 
 impl PartialEq for FullInt {
-    #[must_use]
     fn eq(&self, other: &Self) -> bool {
         self.cmp(other) == Ordering::Equal
     }
 }
 
 impl PartialOrd for FullInt {
-    #[must_use]
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.cmp(other))
     }
 }
 
 impl Ord for FullInt {
-    #[must_use]
     fn cmp(&self, other: &Self) -> Ordering {
         use FullInt::{S, U};
 
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 55292c46bba..c65f10a52bd 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -465,7 +465,10 @@ fn profiler_runtime() {
 #[test]
 fn asm_support() {
     let asms = [
+        #[cfg(bootstrap)]
         ("avr-unknown-gnu-atmega328", false),
+        #[cfg(not(bootstrap))]
+        ("avr-none", false),
         ("i686-unknown-netbsd", true),
         ("riscv32gc-unknown-linux-gnu", true),
         ("riscv64imac-unknown-none-elf", true),
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index f4dac6e947e..54fe7f6eb5a 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -2,6 +2,7 @@
 name = "error_index_generator"
 version = "0.0.0"
 edition = "2021"
+workspace = "../rustbook"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
index fdbf6171c53..608c6605304 100644
--- a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
+++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
@@ -27,6 +27,10 @@ pub struct Args {
     #[arg(long)]
     target_cpu: Option<String>,
 
+    /// The target features
+    #[arg(long)]
+    target_feature: Option<String>,
+
     /// Write output to the filename
     #[arg(short, long)]
     output: PathBuf,
@@ -49,7 +53,7 @@ fn main() -> anyhow::Result<()> {
 
     let args = Args::parse();
 
-    let mut linker = Session::new(args.target, args.target_cpu, args.output);
+    let mut linker = Session::new(args.target, args.target_cpu, args.target_feature, args.output);
 
     linker.add_exported_symbols(args.export_symbol);
 
diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs
index 9f579d10094..dafd847e768 100644
--- a/src/tools/llvm-bitcode-linker/src/linker.rs
+++ b/src/tools/llvm-bitcode-linker/src/linker.rs
@@ -8,6 +8,7 @@ use crate::{Optimization, Target};
 pub struct Session {
     target: Target,
     cpu: Option<String>,
+    feature: Option<String>,
     symbols: Vec<String>,
 
     /// A file that `llvm-link` supports, like a bitcode file or an archive.
@@ -21,7 +22,12 @@ pub struct Session {
 }
 
 impl Session {
-    pub fn new(target: crate::Target, cpu: Option<String>, out_path: PathBuf) -> Self {
+    pub fn new(
+        target: crate::Target,
+        cpu: Option<String>,
+        feature: Option<String>,
+        out_path: PathBuf,
+    ) -> Self {
         let link_path = out_path.with_extension("o");
         let opt_path = out_path.with_extension("optimized.o");
         let sym_path = out_path.with_extension("symbols.txt");
@@ -29,6 +35,7 @@ impl Session {
         Session {
             target,
             cpu,
+            feature,
             symbols: Vec::new(),
             files: Vec::new(),
             link_path,
@@ -134,6 +141,10 @@ impl Session {
             lcc_command.arg("--mcpu").arg(mcpu);
         }
 
+        if let Some(mattr) = &self.feature {
+            lcc_command.arg(&format!("--mattr={}", mattr));
+        }
+
         let lcc_output = lcc_command
             .arg(&self.opt_path)
             .arg("-o").arg(&self.out_path)
diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
index 782303d5f3f..80dd2f39b42 100644
--- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
+++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
@@ -1,6 +1,8 @@
 
 thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
 unsafe precondition(s) violated: ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null and the specified memory ranges do not overlap
+
+This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 thread caused non-unwinding panic. aborting.
diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs
new file mode 100644
index 00000000000..7de4aef422a
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs
@@ -0,0 +1,30 @@
+// Test that transmuting from `&dyn Trait<fn(&'static ())>` to `&dyn Trait<for<'a> fn(&'a ())>` is UB.
+//
+// The vtable of `() as Trait<fn(&'static ())>` and `() as Trait<for<'a> fn(&'a ())>` can have
+// different entries and, because in the former the entry for `foo` is vacant, this test will
+// segfault at runtime.
+
+trait Trait<U> {
+    fn foo(&self)
+    where
+        U: HigherRanked,
+    {
+    }
+}
+impl<T, U> Trait<U> for T {}
+
+trait HigherRanked {}
+impl HigherRanked for for<'a> fn(&'a ()) {}
+
+// 2nd candidate is required so that selecting `(): Trait<fn(&'static ())>` will
+// evaluate the candidates and fail the leak check instead of returning the
+// only applicable candidate.
+trait Unsatisfied {}
+impl<T: Unsatisfied> HigherRanked for T {}
+
+fn main() {
+    let x: &dyn Trait<fn(&'static ())> = &();
+    let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
+    //~^ ERROR: wrong trait in wide pointer vtable
+    y.foo();
+}
diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
new file mode 100644
index 00000000000..cfdf279a605
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
+  --> tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
+   |
+LL |     let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index 6f8adc09640..875891df233 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -9,6 +9,7 @@ fn main() {
     drop_principal();
     modulo_binder();
     modulo_assoc();
+    bidirectional_subtyping();
 }
 
 fn vtable_nop_cast() {
@@ -531,3 +532,32 @@ fn modulo_assoc() {
 
     (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
 }
+
+fn bidirectional_subtyping() {
+    // Test that transmuting between subtypes of dyn traits is fine, even in the
+    // "wrong direction", i.e. going from a lower-ranked to a higher-ranked dyn trait.
+    // Note that compared to the `dyn-transmute-inner-binder` test, the `for` is on the
+    // *outside* here!
+
+    trait Trait<U: ?Sized> {}
+    impl<T, U: ?Sized> Trait<U> for T {}
+
+    struct Wrapper<T: ?Sized>(T);
+
+    let x: &dyn Trait<fn(&'static ())> = &();
+    let _y: &dyn for<'a> Trait<fn(&'a ())> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn for<'a> Trait<fn(&'a ())> = &();
+    let _y: &dyn Trait<fn(&'static ())> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn Trait<dyn Trait<fn(&'static ())>> = &();
+    let _y: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = &();
+    let _y: &dyn Trait<dyn Trait<fn(&'static ())>> = unsafe { std::mem::transmute(x) };
+
+    // This lowers to a ptr-to-ptr cast (which behaves like a transmute)
+    // and not an unsizing coercion:
+    let x: *const dyn for<'a> Trait<&'a ()> = &();
+    let _y: *const Wrapper<dyn Trait<&'static ()>> = x as _;
+}
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index fd4a20278ad..710ba025830 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -253,6 +253,13 @@ impl Rustc {
         self
     }
 
+    /// Specify the target CPU.
+    pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
+        let target_cpu = target_cpu.as_ref();
+        self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
+        self
+    }
+
     /// Specify the crate type.
     pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
         self.cmd.arg("--crate-type");
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index b6f7c44c2ae..f5a7b658123 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -194,6 +194,7 @@ fn layout_of_simd_ty(
         fields,
         backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
         largest_niche: e_ly.largest_niche,
+        uninhabited: false,
         size,
         align,
         max_repr_align: None,
@@ -297,20 +298,17 @@ pub fn layout_of_ty_query(
                 .checked_mul(count, dl)
                 .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
 
-            let backend_repr =
-                if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
-                    BackendRepr::Uninhabited
-                } else {
-                    BackendRepr::Memory { sized: true }
-                };
+            let backend_repr = BackendRepr::Memory { sized: true };
 
             let largest_niche = if count != 0 { element.largest_niche } else { None };
+            let uninhabited = if count != 0 { element.uninhabited } else { false };
 
             Layout {
                 variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr,
                 largest_niche,
+                uninhabited,
                 align: element.align,
                 size,
                 max_repr_align: None,
@@ -325,6 +323,7 @@ pub fn layout_of_ty_query(
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
+                uninhabited: false,
                 align: element.align,
                 size: Size::ZERO,
                 max_repr_align: None,
@@ -337,6 +336,7 @@ pub fn layout_of_ty_query(
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
+            uninhabited: false,
             align: dl.i8_align,
             size: Size::ZERO,
             max_repr_align: None,
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index b31bf61a6fb..ddcf315a267 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -447,6 +447,13 @@ dependencies = [
 ]
 
 [[package]]
+name = "error_index_generator"
+version = "0.0.0"
+dependencies = [
+ "mdbook",
+]
+
+[[package]]
 name = "fastrand"
 version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -867,9 +874,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.44"
+version = "0.4.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9da1e54401fe5d45a664c57e112e70f18e8c5a73e268c179305b932ee864574"
+checksum = "b07d36d96ffe1b5b16ddf2bc80b3b26bb7a498b2a6591061250bf0af8e8095ad"
 dependencies = [
  "ammonia",
  "anyhow",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 9f9846cdee0..6aec0bec0fa 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -1,4 +1,5 @@
 [workspace]
+members = ["../error_index_generator"]
 
 [package]
 name = "rustbook"
@@ -14,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
 [dependencies.mdbook]
-version = "0.4.44"
+version = "0.4.45"
 default-features = false
 features = ["search"]
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e8e7dfe0d84..51e58b4e4fc 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -99,7 +99,6 @@ const EXCEPTIONS: ExceptionList = &[
     ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
     ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
     ("foldhash", "Zlib"),                                    // rustc
-    ("mdbook", "MPL-2.0"),                                   // mdbook
     ("option-ext", "MPL-2.0"),                               // cargo-miri (via `directories`)
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),     // rustc (license is the same as LLVM uses)
     ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0                       // cargo/... (because of serde)
@@ -667,7 +666,7 @@ pub static CRATES: &[&str] = &[
         for extra in expected.difference(&proc_macro_deps) {
             tidy_error!(
                 bad,
-                "`{extra}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
+                "`{extra}` is registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
             );
         }
         if *bad != old_bad {
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 39c9a148e9e..1cb47353469 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -3619,7 +3619,6 @@ ui/resolve/issue-21221-1.rs
 ui/resolve/issue-21221-2.rs
 ui/resolve/issue-21221-3.rs
 ui/resolve/issue-21221-4.rs
-ui/resolve/issue-22692.rs
 ui/resolve/issue-2330.rs
 ui/resolve/issue-23305.rs
 ui/resolve/issue-2356.rs
diff --git a/src/tools/tidy/src/target_policy.rs b/src/tools/tidy/src/target_policy.rs
index 776221d3062..b2681934417 100644
--- a/src/tools/tidy/src/target_policy.rs
+++ b/src/tools/tidy/src/target_policy.rs
@@ -21,6 +21,7 @@ const EXCEPTIONS: &[&str] = &[
     "xtensa_esp32s2_espidf",
     "xtensa_esp32s3_none_elf",
     "xtensa_esp32s3_espidf",
+    "i586_pc_nto_qnx700", // Renamed to i686-pc-nto-qnx700, see https://github.com/rust-lang/rust/issues/136495
 ];
 
 pub fn check(root_path: &Path, bad: &mut bool) {
diff --git a/tests/assembly/asm/avr-modifiers.rs b/tests/assembly/asm/avr-modifiers.rs
index 585fdd7b725..124cad9bef6 100644
--- a/tests/assembly/asm/avr-modifiers.rs
+++ b/tests/assembly/asm/avr-modifiers.rs
@@ -1,6 +1,6 @@
 //@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --target avr-unknown-gnu-atmega328
+//@ compile-flags: --target avr-none -C target-cpu=atmega328p
 //@ needs-llvm-components: avr
 
 #![feature(no_core, asm_experimental_arch)]
diff --git a/tests/assembly/asm/avr-types.rs b/tests/assembly/asm/avr-types.rs
index 25cf3ec3b4b..309405f4d51 100644
--- a/tests/assembly/asm/avr-types.rs
+++ b/tests/assembly/asm/avr-types.rs
@@ -1,6 +1,6 @@
 //@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --target avr-unknown-gnu-atmega328
+//@ compile-flags: --target avr-none -C target-cpu=atmega328p
 //@ needs-llvm-components: avr
 
 #![feature(no_core, asm_experimental_arch)]
diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs
index b629d8769ed..069204bbd34 100644
--- a/tests/assembly/closure-inherit-target-feature.rs
+++ b/tests/assembly/closure-inherit-target-feature.rs
@@ -8,8 +8,9 @@
 
 use std::arch::x86_64::{__m128, _mm_blend_ps};
 
+// Use an explicit return pointer to prevent tail call optimization.
 #[no_mangle]
-pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 {
+pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128, ret: *mut __m128) {
     let f = {
         // check that _mm_blend_ps is not being inlined into the closure
         // CHECK-LABEL: {{sse41_blend_nofeature.*closure.*:}}
@@ -18,9 +19,9 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 {
         // CHECK-NOT: blendps
         // CHECK: ret
         #[inline(never)]
-        |x, y| _mm_blend_ps(x, y, 0b0101)
+        |x, y, ret: *mut __m128| unsafe { *ret = _mm_blend_ps(x, y, 0b0101) }
     };
-    f(x, y)
+    f(x, y, ret);
 }
 
 #[no_mangle]
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index b5c0ee5a107..3e73d2c6eb7 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -216,9 +216,9 @@
 //@ revisions: hexagon_unknown_none_elf
 //@ [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf
 //@ [hexagon_unknown_none_elf] needs-llvm-components: hexagon
-//@ revisions: i586_pc_nto_qnx700
-//@ [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700
-//@ [i586_pc_nto_qnx700] needs-llvm-components: x86
+//@ revisions: i686_pc_nto_qnx700
+//@ [i686_pc_nto_qnx700] compile-flags: --target i686-pc-nto-qnx700
+//@ [i686_pc_nto_qnx700] needs-llvm-components: x86
 //@ revisions: i586_unknown_linux_gnu
 //@ [i586_unknown_linux_gnu] compile-flags: --target i586-unknown-linux-gnu
 //@ [i586_unknown_linux_gnu] needs-llvm-components: x86
diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs
index 1fa4dc821dd..b74d0181c4d 100644
--- a/tests/assembly/targets/targets-pe.rs
+++ b/tests/assembly/targets/targets-pe.rs
@@ -15,9 +15,9 @@
 //@ revisions: arm64ec_pc_windows_msvc
 //@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
 //@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
-//@ revisions: avr_unknown_gnu_atmega328
-//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328
-//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr
+//@ revisions: avr_none
+//@ [avr_none] compile-flags: --target avr-none -C target-cpu=atmega328p
+//@ [avr_none] needs-llvm-components: avr
 //@ revisions: bpfeb_unknown_none
 //@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none
 //@ [bpfeb_unknown_none] needs-llvm-components: bpf
diff --git a/tests/assembly/x86-return-float.rs b/tests/assembly/x86-return-float.rs
index ad760627b3a..2c39c830684 100644
--- a/tests/assembly/x86-return-float.rs
+++ b/tests/assembly/x86-return-float.rs
@@ -33,19 +33,18 @@ use minicore::*;
 // CHECK-LABEL: return_f32:
 #[no_mangle]
 pub fn return_f32(x: f32) -> f32 {
-    // CHECK: movl {{.*}}(%ebp), %eax
-    // CHECK-NOT: ax
-    // CHECK: retl
+    // CHECK: movss {{.*}}(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // CHECK-NEXT: retl
     x
 }
 
 // CHECK-LABEL: return_f64:
 #[no_mangle]
 pub fn return_f64(x: f64) -> f64 {
-    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
-    // CHECK-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL:.*]]
-    // CHECK-NEXT: movsd %[[VAL]], (%[[PTR]])
-    // CHECK: retl
+    // CHECK: movsd {{.*}}(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // CHECK-NEXT: retl
     x
 }
 
@@ -157,7 +156,7 @@ pub unsafe fn call_f32(x: &mut f32) {
     }
     // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
     // CHECK: calll {{()|_}}get_f32
-    // CHECK-NEXT: movl %eax, (%[[PTR]])
+    // CHECK-NEXT: movss %xmm0, (%[[PTR]])
     *x = get_f32();
 }
 
@@ -169,8 +168,7 @@ pub unsafe fn call_f64(x: &mut f64) {
     }
     // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
     // CHECK: calll {{()|_}}get_f64
-    // CHECK: movsd {{.*}}(%{{ebp|esp}}), %[[VAL:.*]]
-    // CHECK-NEXT: movsd %[[VAL:.*]], (%[[PTR]])
+    // CHECK-NEXT: movlps %xmm0, (%[[PTR]])
     *x = get_f64();
 }
 
@@ -315,25 +313,21 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
 #[no_mangle]
 pub fn return_f16(x: f16) -> f16 {
     // CHECK: pushl %ebp
-    // CHECK: movl %esp, %ebp
-    // CHECK: movzwl 8(%ebp), %eax
-    // CHECK: popl %ebp
-    // CHECK: retl
+    // CHECK-NEXT: movl %esp, %ebp
+    // CHECK-NEXT: pinsrw $0, 8(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // CHECK-NEXT: retl
     x
 }
 
 // CHECK-LABEL: return_f128:
 #[no_mangle]
 pub fn return_f128(x: f128) -> f128 {
-    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
-    // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
-    // CHECK-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
-    // CHECK-NEXT: movl [[#%d,OFFSET+12]](%ebp), %[[VAL3:.*]]
-    // CHECK-NEXT: movl [[#%d,OFFSET+16]](%ebp), %[[VAL4:.*]]
-    // CHECK-NEXT: movl %[[VAL4:.*]] 12(%[[PTR]])
-    // CHECK-NEXT: movl %[[VAL3:.*]] 8(%[[PTR]])
-    // CHECK-NEXT: movl %[[VAL2:.*]] 4(%[[PTR]])
-    // CHECK-NEXT: movl %[[VAL1:.*]] (%[[PTR]])
-    // CHECK: retl
+    // CHECK: pushl %ebp
+    // CHECK-NEXT: movl %esp, %ebp
+    // linux-NEXT: movaps 8(%ebp), %xmm0
+    // win-NEXT: movups 8(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // CHECK-NEXT: retl
     x
 }
diff --git a/tests/assembly/x86_64-windows-i128-abi.rs b/tests/assembly/x86_64-windows-i128-abi.rs
new file mode 100644
index 00000000000..d2aefb7daa6
--- /dev/null
+++ b/tests/assembly/x86_64-windows-i128-abi.rs
@@ -0,0 +1,26 @@
+//@ assembly-output: emit-asm
+//@ add-core-stubs
+//@ revisions: msvc softfloat
+//@ compile-flags: -Copt-level=3
+//@[msvc] compile-flags: --target x86_64-pc-windows-msvc
+//@[msvc] needs-llvm-components: x86
+//@[softfloat] compile-flags: --target x86_64-unknown-uefi
+//@[softfloat] needs-llvm-components: x86
+
+#![feature(no_core)]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: ret_i128
+// Hardfloat targets return via xmm0, softfloat targets via rax and rdx.
+// msvc: movaps {{.*}}, %xmm0
+// softfloat: movq (%[[INPUT:.*]]), %rax
+// softfloat-NEXT: movq 8(%[[INPUT]]), %rdx
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn ret_i128(x: &i128) -> i128 {
+    *x
+}
diff --git a/tests/codegen/abi-x86-sse.rs b/tests/codegen/abi-x86-sse.rs
new file mode 100644
index 00000000000..837bf6134b0
--- /dev/null
+++ b/tests/codegen/abi-x86-sse.rs
@@ -0,0 +1,36 @@
+//@ compile-flags: -Z merge-functions=disabled
+
+//@ revisions: x86-64
+//@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86-64] needs-llvm-components: x86
+
+//@ revisions: x86-32
+//@[x86-32] compile-flags: --target i686-unknown-linux-gnu
+//@[x86-32] needs-llvm-components: x86
+
+//@ revisions: x86-32-nosse
+//@[x86-32-nosse] compile-flags: --target i586-unknown-linux-gnu
+//@[x86-32-nosse] needs-llvm-components: x86
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+// Ensure this type is passed without ptr indirection on targets that
+// require SSE2.
+#[repr(simd)]
+pub struct Sse([f32; 4]);
+
+// x86-64: <4 x float> @sse_id(<4 x float> {{[^,]*}})
+// x86-32: <4 x float> @sse_id(<4 x float> {{[^,]*}})
+// x86-32-nosse: void @sse_id(ptr{{( [^,]*)?}} sret([16 x i8]){{( .*)?}}, ptr{{( [^,]*)?}})
+#[no_mangle]
+pub fn sse_id(x: Sse) -> Sse {
+    x
+}
diff --git a/tests/codegen/asm/avr-clobbers.rs b/tests/codegen/asm/avr-clobbers.rs
index 56218cd7bcf..9451127bf04 100644
--- a/tests/codegen/asm/avr-clobbers.rs
+++ b/tests/codegen/asm/avr-clobbers.rs
@@ -1,6 +1,6 @@
 //@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --target avr-unknown-gnu-atmega328
+//@ compile-flags: --target avr-none -C target-cpu=atmega328p
 //@ needs-llvm-components: avr
 
 #![crate_type = "rlib"]
diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs
index ed8acccb1ad..2ec7c86b5f4 100644
--- a/tests/codegen/avr/avr-func-addrspace.rs
+++ b/tests/codegen/avr/avr-func-addrspace.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Copt-level=3 --target=avr-unknown-gnu-atmega328 --crate-type=rlib -C panic=abort
+//@ compile-flags: -Copt-level=3 --target=avr-none -C target-cpu=atmega328p --crate-type=rlib -C panic=abort
 //@ needs-llvm-components: avr
 
 // This test validates that function pointers can be stored in global variables
diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs
index 562a8e6c9e9..d87bab1172a 100644
--- a/tests/codegen/float/f128.rs
+++ b/tests/codegen/float/f128.rs
@@ -1,8 +1,11 @@
 // 32-bit x86 returns float types differently to avoid the x87 stack.
 // 32-bit systems will return 128bit values using a return area pointer.
 // Emscripten aligns f128 to 8 bytes, not 16.
-//@ revisions: x86 bit32 bit64 emscripten
-//@[x86] only-x86
+//@ revisions: x86-sse x86-nosse bit32 bit64 emscripten
+//@[x86-sse] only-x86
+//@[x86-sse] only-rustc_abi-x86-sse2
+//@[x86-nosse] only-x86
+//@[x86-nosse] ignore-rustc_abi-x86-sse2
 //@[bit32] ignore-x86
 //@[bit32] ignore-emscripten
 //@[bit32] only-32bit
@@ -60,7 +63,8 @@ pub fn f128_le(a: f128, b: f128) -> bool {
     a <= b
 }
 
-// x86-LABEL: void @f128_neg({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_neg({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_neg(fp128
 // bit32-LABEL: void @f128_neg({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_neg(
 // emscripten-LABEL: void @f128_neg({{.*}}sret([16 x i8])
@@ -70,7 +74,8 @@ pub fn f128_neg(a: f128) -> f128 {
     -a
 }
 
-// x86-LABEL: void @f128_add({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_add({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_add(fp128
 // bit32-LABEL: void @f128_add({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_add(
 // emscripten-LABEL: void @f128_add({{.*}}sret([16 x i8])
@@ -80,7 +85,8 @@ pub fn f128_add(a: f128, b: f128) -> f128 {
     a + b
 }
 
-// x86-LABEL: void @f128_sub({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_sub({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_sub(fp128
 // bit32-LABEL: void @f128_sub({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_sub(
 // emscripten-LABEL: void @f128_sub({{.*}}sret([16 x i8])
@@ -90,7 +96,8 @@ pub fn f128_sub(a: f128, b: f128) -> f128 {
     a - b
 }
 
-// x86-LABEL: void @f128_mul({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_mul({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_mul(fp128
 // bit32-LABEL: void @f128_mul({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_mul(
 // emscripten-LABEL: void @f128_mul({{.*}}sret([16 x i8])
@@ -100,7 +107,8 @@ pub fn f128_mul(a: f128, b: f128) -> f128 {
     a * b
 }
 
-// x86-LABEL: void @f128_div({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_div({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_div(fp128
 // bit32-LABEL: void @f128_div({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_div(
 // emscripten-LABEL: void @f128_div({{.*}}sret([16 x i8])
@@ -110,7 +118,8 @@ pub fn f128_div(a: f128, b: f128) -> f128 {
     a / b
 }
 
-// x86-LABEL: void @f128_rem({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_rem({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_rem(fp128
 // bit32-LABEL: void @f128_rem({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_rem(
 // emscripten-LABEL: void @f128_rem({{.*}}sret([16 x i8])
@@ -162,7 +171,8 @@ pub fn f128_rem_assign(a: &mut f128, b: f128) {
 
 /* float to float conversions */
 
-// x86-LABEL: i16 @f128_as_f16(
+// x86-sse-LABEL: <2 x i8> @f128_as_f16(
+// x86-nosse-LABEL: i16 @f128_as_f16(
 // bits32-LABEL: half @f128_as_f16(
 // bits64-LABEL: half @f128_as_f16(
 #[no_mangle]
@@ -171,7 +181,8 @@ pub fn f128_as_f16(a: f128) -> f16 {
     a as f16
 }
 
-// x86-LABEL: i32 @f128_as_f32(
+// x86-sse-LABEL: <4 x i8> @f128_as_f32(
+// x86-nosse-LABEL: i32 @f128_as_f32(
 // bit32-LABEL: float @f128_as_f32(
 // bit64-LABEL: float @f128_as_f32(
 // emscripten-LABEL: float @f128_as_f32(
@@ -181,7 +192,8 @@ pub fn f128_as_f32(a: f128) -> f32 {
     a as f32
 }
 
-// x86-LABEL: void @f128_as_f64(
+// x86-sse-LABEL: <8 x i8> @f128_as_f64(
+// x86-nosse-LABEL: void @f128_as_f64({{.*}}sret([8 x i8])
 // bit32-LABEL: double @f128_as_f64(
 // bit64-LABEL: double @f128_as_f64(
 // emscripten-LABEL: double @f128_as_f64(
@@ -191,7 +203,8 @@ pub fn f128_as_f64(a: f128) -> f64 {
     a as f64
 }
 
-// x86-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f128_as_self(
+// x86-nosse-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f128_as_self(
 // emscripten-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
@@ -204,7 +217,8 @@ pub fn f128_as_self(a: f128) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f16_as_f128(
+// x86-nosse-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f16_as_f128(
 // emscripten-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
@@ -214,7 +228,8 @@ pub fn f16_as_f128(a: f16) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f32_as_f128(
+// x86-nosse-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f32_as_f128(
 // emscripten-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
@@ -224,7 +239,8 @@ pub fn f32_as_f128(a: f32) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f64_as_f128(
+// x86-nosse-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f64_as_f128(
 // emscripten-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
@@ -263,7 +279,8 @@ pub fn f128_as_u64(a: f128) -> u64 {
     a as u64
 }
 
-// x86-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
 // bit64-LABEL: i128 @f128_as_u128(
 // emscripten-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
@@ -300,7 +317,8 @@ pub fn f128_as_i64(a: f128) -> i64 {
     a as i64
 }
 
-// x86-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
 // bit64-LABEL: i128 @f128_as_i128(
 // emscripten-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
@@ -312,7 +330,8 @@ pub fn f128_as_i128(a: f128) -> i128 {
 
 /* int to float conversions */
 
-// x86-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @u8_as_f128(
+// x86-nosse-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @u8_as_f128(
 // emscripten-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
@@ -322,7 +341,8 @@ pub fn u8_as_f128(a: u8) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @u16_as_f128(
+// x86-nosse-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @u16_as_f128(
 // emscripten-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
@@ -332,7 +352,8 @@ pub fn u16_as_f128(a: u16) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @u32_as_f128(
+// x86-nosse-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @u32_as_f128(
 // emscripten-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
@@ -342,7 +363,8 @@ pub fn u32_as_f128(a: u32) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @u64_as_f128(
+// x86-nosse-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @u64_as_f128(
 // emscripten-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
@@ -352,7 +374,8 @@ pub fn u64_as_f128(a: u64) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @u128_as_f128(
+// x86-nosse-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @u128_as_f128(
 // emscripten-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
@@ -362,7 +385,8 @@ pub fn u128_as_f128(a: u128) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @i8_as_f128(
+// x86-nosse-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @i8_as_f128(
 // emscripten-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
@@ -372,7 +396,8 @@ pub fn i8_as_f128(a: i8) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @i16_as_f128(
+// x86-nosse-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @i16_as_f128(
 // emscripten-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
@@ -382,7 +407,8 @@ pub fn i16_as_f128(a: i16) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @i32_as_f128(
+// x86-nosse-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @i32_as_f128(
 // emscripten-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
@@ -392,7 +418,8 @@ pub fn i32_as_f128(a: i32) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @i64_as_f128(
+// x86-nosse-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @i64_as_f128(
 // emscripten-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
@@ -402,7 +429,8 @@ pub fn i64_as_f128(a: i64) -> f128 {
     a as f128
 }
 
-// x86-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @i128_as_f128(
+// x86-nosse-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @i128_as_f128(
 // emscripten-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs
index 5c3a5893b9d..0c40606ad8a 100644
--- a/tests/codegen/float/f16.rs
+++ b/tests/codegen/float/f16.rs
@@ -1,7 +1,10 @@
 // 32-bit x86 returns float types differently to avoid the x87 stack.
 // 32-bit systems will return 128bit values using a return area pointer.
-//@ revisions: x86 bit32 bit64
-//@[x86] only-x86
+//@ revisions: x86-sse x86-nosse bit32 bit64
+//@[x86-sse] only-x86
+//@[x86-sse] only-rustc_abi-x86-sse2
+//@[x86-nosse] only-x86
+//@[x86-nosse] ignore-rustc_abi-x86-sse2
 //@[bit32] ignore-x86
 //@[bit32] only-32bit
 //@[bit64] ignore-x86
@@ -59,8 +62,10 @@ pub fn f16_le(a: f16, b: f16) -> bool {
 }
 
 // This is where we check the argument and return ABI for f16.
-// other-LABEL: half @f16_neg(half
-// x86-LABEL: i16 @f16_neg(half
+// bit32-LABEL: half @f16_neg(half
+// bit64-LABEL: half @f16_neg(half
+// x86-sse-LABEL: <2 x i8> @f16_neg(half
+// x86-nosse-LABEL: i16 @f16_neg(half
 #[no_mangle]
 pub fn f16_neg(a: f16) -> f16 {
     // CHECK: fneg half %{{.+}}
@@ -144,17 +149,23 @@ pub fn f16_rem_assign(a: &mut f16, b: f16) {
 
 /* float to float conversions */
 
-// other-LABEL: half @f16_as_self(
-// x86-LABEL: i16 @f16_as_self(
+// bit32-LABEL: half @f16_as_self(
+// bit64-LABEL: half @f16_as_self(
+// x86-sse-LABEL: <2 x i8> @f16_as_self(
+// x86-nosse-LABEL: i16 @f16_as_self(
 #[no_mangle]
 pub fn f16_as_self(a: f16) -> f16 {
-    // other-CHECK: ret half %{{.+}}
-    // x86-CHECK: bitcast half
-    // x86-CHECK: ret i16
+    // bit32-CHECK: ret half %{{.+}}
+    // bit64-CHECK: ret half %{{.+}}
+    // x86-sse-CHECK: bitcast half
+    // x86-nosse-CHECK: bitcast half
+    // x86-sse-CHECK: ret i16
+    // x86-nosse-CHECK: ret i16
     a as f16
 }
 
-// x86-LABEL: i32 @f16_as_f32(
+// x86-sse-LABEL: <4 x i8> @f16_as_f32(
+// x86-nosse-LABEL: i32 @f16_as_f32(
 // bit32-LABEL: float @f16_as_f32(
 // bit64-LABEL: float @f16_as_f32(
 #[no_mangle]
@@ -163,7 +174,8 @@ pub fn f16_as_f32(a: f16) -> f32 {
     a as f32
 }
 
-// x86-LABEL: void @f16_as_f64(
+// x86-sse-LABEL: <8 x i8> @f16_as_f64(
+// x86-nosse-LABEL: void @f16_as_f64({{.*}}sret([8 x i8])
 // bit32-LABEL: double @f16_as_f64(
 // bit64-LABEL: double @f16_as_f64(
 #[no_mangle]
@@ -172,7 +184,8 @@ pub fn f16_as_f64(a: f16) -> f64 {
     a as f64
 }
 
-// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: <16 x i8> @f16_as_f128(
+// x86-nosse-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
 // bit64-LABEL: fp128 @f16_as_f128(
 #[no_mangle]
@@ -231,7 +244,8 @@ pub fn f16_as_u64(a: f16) -> u64 {
     a as u64
 }
 
-// x86-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
 // bit64-LABEL: i128 @f16_as_u128(
 #[no_mangle]
@@ -267,7 +281,8 @@ pub fn f16_as_i64(a: f16) -> i64 {
     a as i64
 }
 
-// x86-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
+// x86-sse-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
+// x86-nosse-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
 // bit32-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
 // bit64-LABEL: i128 @f16_as_i128(
 #[no_mangle]
diff --git a/tests/codegen/i128-x86-callconv.rs b/tests/codegen/i128-x86-callconv.rs
index 9a9c9002fc0..41c30c09c1a 100644
--- a/tests/codegen/i128-x86-callconv.rs
+++ b/tests/codegen/i128-x86-callconv.rs
@@ -4,13 +4,18 @@
 //@ compile-flags: -Copt-level=1
 
 //@ add-core-stubs
-//@ revisions: MSVC MINGW
+//@ revisions: MSVC MINGW softfloat
 //@ [MSVC] needs-llvm-components: x86
-//@ [MINGW] needs-llvm-components: x86
 //@ [MSVC] compile-flags: --target x86_64-pc-windows-msvc
-//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu
+// Use `WIN` as a common prefix for MSVC and MINGW but *not* the softfloat test.
 //@ [MSVC] filecheck-flags: --check-prefix=WIN
+//@ [MINGW] needs-llvm-components: x86
+//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu
 //@ [MINGW] filecheck-flags: --check-prefix=WIN
+// The `x86_64-unknown-uefi` target also uses the Windows calling convention,
+// but does not have SSE registers available.
+//@ [softfloat] needs-llvm-components: x86
+//@ [softfloat] compile-flags: --target x86_64-unknown-uefi
 
 #![crate_type = "lib"]
 #![no_std]
@@ -28,24 +33,26 @@ extern "C" {
 pub extern "C" fn pass(_arg0: u32, arg1: i128) {
     // CHECK-LABEL: @pass(
     // i128 is passed indirectly on Windows. It should load the pointer to the stack and pass
-    // a pointer to that allocation.
-    // WIN-SAME: %_arg0, ptr{{.*}} %arg1)
-    // WIN: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16
-    // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
-    // WIN: store i128 [[LOADED]], ptr [[PASS]]
-    // WIN: call void @extern_call
+    // a pointer to that allocation. The softfloat ABI works the same.
+    // CHECK-SAME: %_arg0, ptr{{.*}} %arg1)
+    // CHECK: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16
+    // CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
+    // CHECK: store i128 [[LOADED]], ptr [[PASS]]
+    // CHECK: call void @extern_call
     unsafe { extern_call(arg1) };
 }
 
 // Check that we produce the correct return ABI
 #[no_mangle]
 pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 {
-    // CHECK-LABEL: @ret(
+    // WIN-LABEL: @ret(
     // i128 is returned in xmm0 on Windows
     // FIXME(#134288): This may change for the `-msvc` targets in the future.
     // WIN-SAME: i32{{.*}} %_arg0, ptr{{.*}} %arg1)
     // WIN: [[LOADED:%[_0-9]+]] = load <16 x i8>, ptr %arg1
     // WIN-NEXT: ret <16 x i8> [[LOADED]]
+    // The softfloat ABI returns this indirectly.
+    // softfloat-LABEL: i128 @ret(i32{{.*}} %_arg0, ptr{{.*}} %arg1)
     arg1
 }
 
@@ -57,6 +64,7 @@ pub extern "C" fn forward(dst: *mut i128) {
     // WIN: [[RETURNED:%[_0-9]+]] = tail call <16 x i8> @extern_ret()
     // WIN: store <16 x i8> [[RETURNED]], ptr %dst
     // WIN: ret void
+    // softfloat: [[RETURNED:%[_0-9]+]] = tail call {{.*}}i128 @extern_ret()
     unsafe { *dst = extern_ret() };
 }
 
@@ -70,10 +78,10 @@ struct RetAggregate {
 pub extern "C" fn ret_aggregate(_arg0: u32, arg1: i128) -> RetAggregate {
     // CHECK-LABEL: @ret_aggregate(
     // Aggregates should also be returned indirectly
-    // WIN-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1)
-    // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
-    // WIN: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]]
-    // WIN: store i128 [[LOADED]], ptr [[GEP]]
-    // WIN: ret void
+    // CHECK-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1)
+    // CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
+    // CHECK: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]]
+    // CHECK: store i128 [[LOADED]], ptr [[GEP]]
+    // CHECK: ret void
     RetAggregate { a: 1, b: arg1 }
 }
diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs
index 5ded0e192fa..8ff5cc8ee4f 100644
--- a/tests/codegen/intrinsics/transmute-niched.rs
+++ b/tests/codegen/intrinsics/transmute-niched.rs
@@ -170,7 +170,7 @@ pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool {
     // OPT: call void @llvm.assume(i1 %2)
     // CHECK-NOT: icmp
     // CHECK-NOT: assume
-    // CHECK: %[[R:.+]] = trunc i8 %x to i1
+    // CHECK: %[[R:.+]] = trunc{{( nuw)?}} i8 %x to i1
     // CHECK: ret i1 %[[R]]
 
     transmute(x)
diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs
index fe68f183667..be45e4db90f 100644
--- a/tests/codegen/intrinsics/transmute-x64.rs
+++ b/tests/codegen/intrinsics/transmute-x64.rs
@@ -6,15 +6,6 @@
 use std::arch::x86_64::{__m128, __m128i, __m256i};
 use std::mem::transmute;
 
-// CHECK-LABEL: @check_sse_float_to_int(
-#[no_mangle]
-pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i {
-    // CHECK-NOT: alloca
-    // CHECK: %0 = load <4 x float>, ptr %x, align 16
-    // CHECK: store <4 x float> %0, ptr %_0, align 16
-    transmute(x)
-}
-
 // CHECK-LABEL: @check_sse_pair_to_avx(
 #[no_mangle]
 pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i {
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 5b40a6a12c0..ff297b27065 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -11,6 +11,9 @@ use std::intrinsics::mir::*;
 use std::intrinsics::{transmute, transmute_unchecked};
 use std::mem::MaybeUninit;
 
+// FIXME(LLVM18REMOVED): `trunc nuw` doesn't exist in LLVM 18, so once we no
+// longer support it the optional flag checks can be changed to required.
+
 pub enum ZstNever {}
 
 #[repr(align(2))]
@@ -153,7 +156,7 @@ pub unsafe fn check_from_newtype(x: Scalar64) -> u64 {
 pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
     // CHECK: %x = alloca [1 x i8], align 1
     // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1
-    // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1
+    // CHECK: %[[BOOL:.+]] = trunc{{( nuw)?}} i8 %[[BYTE]] to i1
     // CHECK: ret i1 %[[BOOL]]
     transmute(x)
 }
@@ -171,7 +174,7 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
 #[no_mangle]
 pub unsafe fn check_byte_to_bool(x: u8) -> bool {
     // CHECK-NOT: alloca
-    // CHECK: %[[R:.+]] = trunc i8 %x to i1
+    // CHECK: %[[R:.+]] = trunc{{( nuw)?}} i8 %x to i1
     // CHECK: ret i1 %[[R]]
     transmute(x)
 }
@@ -284,7 +287,7 @@ pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] {
 #[no_mangle]
 pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) {
     // CHECK-NOT: alloca
-    // CHECK: trunc i8 %x.0 to i1
+    // CHECK: trunc{{( nuw)?}} i8 %x.0 to i1
     // CHECK: zext i1 %x.1 to i8
     transmute(x)
 }
@@ -338,7 +341,7 @@ pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) {
     // CHECK: store i8 %[[WIDER]]
 
     // CHECK: %[[BYTE:.+]] = load i8
-    // CHECK: trunc i8 %[[BYTE:.+]] to i1
+    // CHECK: trunc{{( nuw)?}} i8 %[[BYTE:.+]] to i1
     // CHECK: load i32
     transmute(x)
 }
diff --git a/tests/codegen/issues/issue-32031.rs b/tests/codegen/issues/issue-32031.rs
index 4d6895166f1..559e8d947fb 100644
--- a/tests/codegen/issues/issue-32031.rs
+++ b/tests/codegen/issues/issue-32031.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: -C no-prepopulate-passes -Copt-level=0
 // 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack.
 //@ revisions: x86 other
-//@[x86] only-x86
+//@[x86] only-rustc_abi-x86-sse2
 //@[other] ignore-x86
 
 #![crate_type = "lib"]
@@ -10,7 +10,7 @@
 pub struct F32(f32);
 
 // other: define{{.*}}float @add_newtype_f32(float %a, float %b)
-// x86: define{{.*}}i32 @add_newtype_f32(float %a, float %b)
+// x86: define{{.*}}<4 x i8> @add_newtype_f32(float %a, float %b)
 #[inline(never)]
 #[no_mangle]
 pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
@@ -21,7 +21,7 @@ pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
 pub struct F64(f64);
 
 // other: define{{.*}}double @add_newtype_f64(double %a, double %b)
-// x86: define{{.*}}void @add_newtype_f64(ptr{{.*}}sret([8 x i8]){{.*}}%_0, double %a, double %b)
+// x86: define{{.*}}<8 x i8> @add_newtype_f64(double %a, double %b)
 #[inline(never)]
 #[no_mangle]
 pub fn add_newtype_f64(a: F64, b: F64) -> F64 {
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index 75f989d6e12..0d21d510557 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -1,5 +1,14 @@
 //
 //@ compile-flags: -C no-prepopulate-passes
+// LLVM IR isn't very portable and the one tested here depends on the ABI
+// which is different between x86 (where we use SSE registers) and others.
+// `x86-64` and `x86-32-sse2` are identical, but compiletest does not support
+// taking the union of multiple `only` annotations.
+//@ revisions: x86-64 x86-32-sse2 other
+//@[x86-64] only-x86_64
+//@[x86-32-sse2] only-rustc_abi-x86-sse2
+//@[other] ignore-rustc_abi-x86-sse2
+//@[other] ignore-x86_64
 
 #![crate_type = "lib"]
 #![allow(non_camel_case_types)]
@@ -38,7 +47,9 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> {
 #[no_mangle]
 pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
     // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
-    // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
+    // x86-32: ret <4 x float> %[[VAL:.+]]
+    // x86-64: ret <4 x float> %[[VAL:.+]]
+    // other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
     unsafe { std::mem::transmute(x) }
 }
 
@@ -53,6 +64,8 @@ pub fn build_array_t(x: [f32; 4]) -> T {
 #[no_mangle]
 pub fn build_array_transmute_t(x: [f32; 4]) -> T {
     // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
-    // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
+    // x86-32: ret <4 x float> %[[VAL:.+]]
+    // x86-64: ret <4 x float> %[[VAL:.+]]
+    // other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
     unsafe { std::mem::transmute(x) }
 }
diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs
index 1df09c96e6c..a27d5e3af45 100644
--- a/tests/codegen/simd/packed-simd.rs
+++ b/tests/codegen/simd/packed-simd.rs
@@ -1,4 +1,5 @@
 //@ revisions:opt3 noopt
+//@ only-x86_64
 //@[opt3] compile-flags: -Copt-level=3
 //@[noopt] compile-flags: -Cno-prepopulate-passes
 
@@ -14,14 +15,14 @@ use core::{mem, ptr};
 
 #[repr(simd, packed)]
 #[derive(Copy, Clone)]
-pub struct Simd<T, const N: usize>([T; N]);
+pub struct PackedSimd<T, const N: usize>([T; N]);
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
 pub struct FullSimd<T, const N: usize>([T; N]);
 
 // non-powers-of-two have padding and need to be expanded to full vectors
-fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
+fn load<T, const N: usize>(v: PackedSimd<T, N>) -> FullSimd<T, N> {
     unsafe {
         let mut tmp = mem::MaybeUninit::<FullSimd<T, N>>::uninit();
         ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
@@ -29,18 +30,16 @@ fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
     }
 }
 
-// CHECK-LABEL: square_packed_full
-// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
-// CHECK-SAME: ptr{{[a-z_ ]*}} align 4
+// CHECK-LABEL: define <3 x float> @square_packed_full(ptr{{[a-z_ ]*}} align 4 {{[^,]*}})
 #[no_mangle]
-pub fn square_packed_full(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
-    // CHECK-NEXT: start
-    // noopt: alloca [[RET_TYPE]], [[RET_ALIGN]]
-    // CHECK: load <3 x float>
+pub fn square_packed_full(x: PackedSimd<f32, 3>) -> FullSimd<f32, 3> {
+    // The unoptimized version of this is not very interesting to check
+    // since `load` does not get inlined.
+    // opt3-NEXT: start:
+    // opt3-NEXT: load <3 x float>
     let x = load(x);
-    // CHECK: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
-    // CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]]
-    // CHECK-NEXT: ret void
+    // opt3-NEXT: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
+    // opt3-NEXT: ret <3 x float> [[VREG:%[a-z0-9_]+]]
     unsafe { intrinsics::simd_mul(x, x) }
 }
 
@@ -48,7 +47,7 @@ pub fn square_packed_full(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
 // CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align 4]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
 // CHECK-SAME: ptr{{[a-z_ ]*}} align 4
 #[no_mangle]
-pub fn square_packed(x: Simd<f32, 3>) -> Simd<f32, 3> {
+pub fn square_packed(x: PackedSimd<f32, 3>) -> PackedSimd<f32, 3> {
     // CHECK-NEXT: start
     // CHECK-NEXT: load <3 x float>
     // noopt-NEXT: load <3 x float>
diff --git a/tests/codegen/simd/project-to-simd-array-field.rs b/tests/codegen/simd/project-to-simd-array-field.rs
new file mode 100644
index 00000000000..29fab640633
--- /dev/null
+++ b/tests/codegen/simd/project-to-simd-array-field.rs
@@ -0,0 +1,31 @@
+//@compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+#![feature(repr_simd, core_intrinsics)]
+
+#[allow(non_camel_case_types)]
+#[derive(Clone, Copy)]
+#[repr(simd)]
+struct i32x4([i32; 4]);
+
+#[inline(always)]
+fn to_array4(a: i32x4) -> [i32; 4] {
+    a.0
+}
+
+// CHECK-LABEL: simd_add_self_then_return_array(
+// CHECK-SAME: ptr{{.+}}sret{{.+}}%[[RET:.+]],
+// CHECK-SAME: ptr{{.+}}%a)
+#[no_mangle]
+pub fn simd_add_self_then_return_array(a: &i32x4) -> [i32; 4] {
+    // It would be nice to just ban `.0` into simd types,
+    // but until we do this has to keep working.
+    // See also <https://github.com/rust-lang/rust/issues/105439>
+
+    // CHECK: %[[T1:.+]] = load <4 x i32>, ptr %a
+    // CHECK: %[[T2:.+]] = shl <4 x i32> %[[T1]], {{splat \(i32 1\)|<i32 1, i32 1, i32 1, i32 1>}}
+    // CHECK: store <4 x i32> %[[T2]], ptr %[[RET]]
+    let a = *a;
+    let b = unsafe { core::intrinsics::simd::simd_add(a, a) };
+    to_array4(b)
+}
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
index 98a1b961a64..87907e7ad0a 100644
--- a/tests/codegen/slice-iter-nonnull.rs
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -14,11 +14,11 @@
 // CHECK-LABEL: @slice_iter_next(
 #[no_mangle]
 pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
-    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
-    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
-    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
     // CHECK: icmp eq ptr %[[START]], %[[END]]
diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs
index 43da7c1781e..c080259a917 100644
--- a/tests/codegen/transmute-scalar.rs
+++ b/tests/codegen/transmute-scalar.rs
@@ -26,7 +26,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
 }
 
 // CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8{{.*}} %byte)
-// CHECK: %_0 = trunc i8 %byte to i1
+// CHECK: %_0 = trunc{{( nuw)?}} i8 %byte to i1
 // CHECK-NEXT: ret i1 %_0
 #[no_mangle]
 pub unsafe fn byte_to_bool(byte: u8) -> bool {
diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs
index b27eb73c0cc..9fccaf2252e 100644
--- a/tests/codegen/unchecked_shifts.rs
+++ b/tests/codegen/unchecked_shifts.rs
@@ -1,4 +1,10 @@
-//@ compile-flags: -Copt-level=3
+//@ revisions: LLVM18 LLVM19PLUS
+//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
+//@[LLVM18] exact-llvm-major-version: 18
+//@[LLVM19PLUS] min-llvm-version: 19
+
+// This runs mir-opts to inline the standard library call, but doesn't run LLVM
+// optimizations so it doesn't need to worry about them adding more flags.
 
 #![crate_type = "lib"]
 #![feature(unchecked_shifts)]
@@ -17,13 +23,10 @@ pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 {
 // CHECK-LABEL: @unchecked_shl_unsigned_smaller
 #[no_mangle]
 pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
-    // This uses -DAG to avoid failing on irrelevant reorderings,
-    // like emitting the truncation earlier.
-
-    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 16
-    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
-    // CHECK-DAG: %[[TRUNC:.+]] = trunc{{( nuw)?( nsw)?}} i32 %b to i16
-    // CHECK-DAG: shl i16 %a, %[[TRUNC]]
+    // CHECK-NOT: assume
+    // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16
+    // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16
+    // CHECK: shl i16 %a, %[[TRUNC]]
     a.unchecked_shl(b)
 }
 
@@ -31,7 +34,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
 #[no_mangle]
 pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
     // CHECK-NOT: assume
-    // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64
+    // CHECK: %[[EXT:.+]] = zext i32 %b to i64
     // CHECK: shl i64 %a, %[[EXT]]
     a.unchecked_shl(b)
 }
@@ -49,13 +52,10 @@ pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 {
 // CHECK-LABEL: @unchecked_shr_signed_smaller
 #[no_mangle]
 pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
-    // This uses -DAG to avoid failing on irrelevant reorderings,
-    // like emitting the truncation earlier.
-
-    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 16
-    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
-    // CHECK-DAG: %[[TRUNC:.+]] = trunc{{( nuw)?( nsw)?}}  i32 %b to i16
-    // CHECK-DAG: ashr i16 %a, %[[TRUNC]]
+    // CHECK-NOT: assume
+    // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16
+    // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16
+    // CHECK: ashr i16 %a, %[[TRUNC]]
     a.unchecked_shr(b)
 }
 
@@ -63,7 +63,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
 #[no_mangle]
 pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
     // CHECK-NOT: assume
-    // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64
+    // CHECK: %[[EXT:.+]] = zext i32 %b to i64
     // CHECK: ashr i64 %a, %[[EXT]]
     a.unchecked_shr(b)
 }
@@ -72,7 +72,7 @@ pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
 #[no_mangle]
 pub unsafe fn unchecked_shr_u128_i8(a: u128, b: i8) -> u128 {
     // CHECK-NOT: assume
-    // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i8 %b to i128
+    // CHECK: %[[EXT:.+]] = zext i8 %b to i128
     // CHECK: lshr i128 %a, %[[EXT]]
     std::intrinsics::unchecked_shr(a, b)
 }
@@ -81,7 +81,7 @@ pub unsafe fn unchecked_shr_u128_i8(a: u128, b: i8) -> u128 {
 #[no_mangle]
 pub unsafe fn unchecked_shl_i128_u8(a: i128, b: u8) -> i128 {
     // CHECK-NOT: assume
-    // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i8 %b to i128
+    // CHECK: %[[EXT:.+]] = zext i8 %b to i128
     // CHECK: shl i128 %a, %[[EXT]]
     std::intrinsics::unchecked_shl(a, b)
 }
@@ -89,25 +89,19 @@ pub unsafe fn unchecked_shl_i128_u8(a: i128, b: u8) -> i128 {
 // CHECK-LABEL: @unchecked_shl_u8_i128
 #[no_mangle]
 pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 {
-    // This uses -DAG to avoid failing on irrelevant reorderings,
-    // like emitting the truncation earlier.
-
-    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i128 %b, 8
-    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
-    // CHECK-DAG: %[[TRUNC:.+]] = trunc{{( nuw)?( nsw)?}} i128 %b to i8
-    // CHECK-DAG: shl i8 %a, %[[TRUNC]]
+    // CHECK-NOT: assume
+    // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8
+    // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8
+    // CHECK: shl i8 %a, %[[TRUNC]]
     std::intrinsics::unchecked_shl(a, b)
 }
 
 // CHECK-LABEL: @unchecked_shr_i8_u128
 #[no_mangle]
 pub unsafe fn unchecked_shr_i8_u128(a: i8, b: u128) -> i8 {
-    // This uses -DAG to avoid failing on irrelevant reorderings,
-    // like emitting the truncation earlier.
-
-    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i128 %b, 8
-    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
-    // CHECK-DAG: %[[TRUNC:.+]] = trunc{{( nuw)?( nsw)?}} i128 %b to i8
-    // CHECK-DAG: ashr i8 %a, %[[TRUNC]]
+    // CHECK-NOT: assume
+    // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8
+    // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8
+    // CHECK: ashr i8 %a, %[[TRUNC]]
     std::intrinsics::unchecked_shr(a, b)
 }
diff --git a/tests/codegen/uninhabited-transparent-return-abi.rs b/tests/codegen/uninhabited-transparent-return-abi.rs
new file mode 100644
index 00000000000..6e8b1683163
--- /dev/null
+++ b/tests/codegen/uninhabited-transparent-return-abi.rs
@@ -0,0 +1,44 @@
+//@ compile-flags: -Copt-level=3
+
+// See https://github.com/rust-lang/rust/issues/135802
+
+#![crate_type = "lib"]
+
+enum Void {}
+
+// Should be ABI-compatible with T, but wasn't prior to the PR adding this test.
+#[repr(transparent)]
+struct NoReturn<T>(T, Void);
+
+// Returned by invisible reference (in most ABIs)
+#[allow(dead_code)]
+struct Large(u64, u64, u64);
+
+extern "Rust" {
+    fn opaque() -> NoReturn<Large>;
+    fn opaque_with_arg(rsi: u32) -> NoReturn<Large>;
+}
+
+// CHECK-LABEL: @test_uninhabited_ret_by_ref
+#[no_mangle]
+pub fn test_uninhabited_ret_by_ref() {
+    // CHECK: %_1 = alloca [24 x i8], align {{8|4}}
+    // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_1)
+    // CHECK-NEXT: call void @opaque(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_1) #2
+    // CHECK-NEXT: unreachable
+    unsafe {
+        opaque();
+    }
+}
+
+// CHECK-LABEL: @test_uninhabited_ret_by_ref_with_arg
+#[no_mangle]
+pub fn test_uninhabited_ret_by_ref_with_arg(rsi: u32) {
+    // CHECK: %_2 = alloca [24 x i8], align {{8|4}}
+    // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_2)
+    // CHECK-NEXT: call void @opaque_with_arg(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_2, i32 noundef %rsi) #2
+    // CHECK-NEXT: unreachable
+    unsafe {
+        opaque_with_arg(rsi);
+    }
+}
diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs
index 92d40d8ac14..28acc4de2f3 100644
--- a/tests/codegen/union-abi.rs
+++ b/tests/codegen/union-abi.rs
@@ -2,8 +2,11 @@
 //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
 // 32-bit x86 returns `f32` differently to avoid the x87 stack.
 // 32-bit systems will return 128bit values using a return area pointer.
-//@ revisions: x86 bit32 bit64
-//@[x86] only-x86
+//@ revisions: x86-sse x86-nosse bit32 bit64
+//@[x86-sse] only-x86
+//@[x86-sse] only-rustc_abi-x86-sse2
+//@[x86-nosse] only-x86
+//@[x86-nosse] ignore-rustc_abi-x86-sse2
 //@[bit32] ignore-x86
 //@[bit32] only-32bit
 //@[bit64] ignore-x86
@@ -75,7 +78,8 @@ pub union UnionF32 {
     a: f32,
 }
 
-// x86: define {{(dso_local )?}}i32 @test_UnionF32(float %_1)
+// x86-sse: define {{(dso_local )?}}<4 x i8> @test_UnionF32(float %_1)
+// x86-nosse: define {{(dso_local )?}}i32 @test_UnionF32(float %_1)
 // bit32: define {{(dso_local )?}}float @test_UnionF32(float %_1)
 // bit64: define {{(dso_local )?}}float @test_UnionF32(float %_1)
 #[no_mangle]
@@ -88,7 +92,8 @@ pub union UnionF32F32 {
     b: f32,
 }
 
-// x86: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1)
+// x86-sse: define {{(dso_local )?}}<4 x i8> @test_UnionF32F32(float %_1)
+// x86-nosse: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1)
 // bit32: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
 // bit64: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
 #[no_mangle]
@@ -110,7 +115,8 @@ pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 {
 pub union UnionU128 {
     a: u128,
 }
-// x86: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
+// x86-sse: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
+// x86-nosse: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
 // bit32: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
 // bit64: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
 #[no_mangle]
@@ -136,4 +142,4 @@ pub union UnionBool {
 pub fn test_UnionBool(b: UnionBool) -> bool {
     unsafe { b.b }
 }
-// CHECK: %_0 = trunc i8 %b to i1
+// CHECK: %_0 = trunc{{( nuw)?}} i8 %b to i1
diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map
index 3c740d80ea0..3deacbc8e12 100644
--- a/tests/coverage/holes.cov-map
+++ b/tests/coverage/holes.cov-map
@@ -1,52 +1,57 @@
 Function name: <holes::main::MyStruct>::_method (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 25, 09, 00, 1d]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 2b, 09, 00, 1d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 37, 9) to (start + 0, 29)
+- Code(Zero) at (prev + 43, 9) to (start + 0, 29)
 Highest counter ID seen: (none)
 
 Function name: holes::main
-Raw bytes (44): 0x[01, 01, 00, 08, 01, 08, 01, 06, 11, 01, 0f, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 01, 02]
+Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
-Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 8, 1) to (start + 6, 17)
-- Code(Counter(0)) at (prev + 15, 5) to (start + 0, 18)
+Number of file 0 mappings: 13
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18)
+- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18)
 - Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
 - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18)
 - Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
 - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15)
 - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15)
-- Code(Counter(0)) at (prev + 10, 5) to (start + 1, 2)
+- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13)
+- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2)
 Highest counter ID seen: c0
 
 Function name: holes::main::_unused_fn (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 17]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 1f, 05, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 25, 5) to (start + 0, 23)
+- Code(Zero) at (prev + 31, 5) to (start + 0, 23)
 Highest counter ID seen: (none)
 
 Function name: holes::main::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 09, 02, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 18, 9) to (start + 2, 10)
+- Code(Zero) at (prev + 24, 9) to (start + 2, 10)
 Highest counter ID seen: (none)
 
 Function name: holes::main::{closure#1} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 3d, 09, 02, 0a]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 4b, 09, 02, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 61, 9) to (start + 2, 10)
+- Code(Zero) at (prev + 75, 9) to (start + 2, 10)
 Highest counter ID seen: (none)
 
diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage
index 6e65435f7e3..1b45c12156a 100644
--- a/tests/coverage/holes.coverage
+++ b/tests/coverage/holes.coverage
@@ -7,10 +7,16 @@
    LL|       |
    LL|      1|fn main() {
    LL|      1|    black_box(());
-   LL|      1|
-   LL|      1|    // Splitting this across multiple lines makes it easier to see where the
-   LL|      1|    // coverage mapping regions begin and end.
-   LL|      1|    #[rustfmt::skip]
+   LL|       |
+   LL|       |    static MY_STATIC: () = ();
+   LL|       |
+   LL|      1|    black_box(());
+   LL|       |
+   LL|       |    const MY_CONST: () = ();
+   LL|       |
+   LL|       |    // Splitting this across multiple lines makes it easier to see where the
+   LL|       |    // coverage mapping regions begin and end.
+   LL|       |    #[rustfmt::skip]
    LL|      1|    let _closure =
    LL|       |        |
    LL|       |            _arg: (),
@@ -39,6 +45,14 @@
    LL|       |
    LL|      1|    black_box(());
    LL|       |
+   LL|       |    trait MyTrait {}
+   LL|       |
+   LL|      1|    black_box(());
+   LL|       |
+   LL|       |    impl MyTrait for MyStruct {}
+   LL|       |
+   LL|      1|    black_box(());
+   LL|       |
    LL|       |    macro_rules! _my_macro {
    LL|       |        () => {};
    LL|       |    }
@@ -64,5 +78,24 @@
    LL|       |        ;
    LL|       |
    LL|      1|    black_box(());
+   LL|      1|
+   LL|      1|    // This tests the edge case of a const block nested inside an "anon const",
+   LL|      1|    // such as the length of an array literal. Handling this case requires
+   LL|      1|    // `nested_filter::OnlyBodies` or equivalent.
+   LL|      1|    #[rustfmt::skip]
+   LL|      1|    let _const_block_inside_anon_const =
+   LL|      1|        [
+   LL|      1|            0
+   LL|      1|            ;
+   LL|      1|            7
+   LL|      1|            +
+   LL|      1|            const
+   LL|       |            {
+   LL|       |                3
+   LL|      1|            }
+   LL|      1|        ]
+   LL|      1|        ;
+   LL|      1|
+   LL|      1|    black_box(());
    LL|      1|}
 
diff --git a/tests/coverage/holes.rs b/tests/coverage/holes.rs
index b3a71e759c8..7f6671772c3 100644
--- a/tests/coverage/holes.rs
+++ b/tests/coverage/holes.rs
@@ -8,6 +8,12 @@ use core::hint::black_box;
 fn main() {
     black_box(());
 
+    static MY_STATIC: () = ();
+
+    black_box(());
+
+    const MY_CONST: () = ();
+
     // Splitting this across multiple lines makes it easier to see where the
     // coverage mapping regions begin and end.
     #[rustfmt::skip]
@@ -39,6 +45,14 @@ fn main() {
 
     black_box(());
 
+    trait MyTrait {}
+
+    black_box(());
+
+    impl MyTrait for MyStruct {}
+
+    black_box(());
+
     macro_rules! _my_macro {
         () => {};
     }
@@ -64,4 +78,23 @@ fn main() {
         ;
 
     black_box(());
+
+    // This tests the edge case of a const block nested inside an "anon const",
+    // such as the length of an array literal. Handling this case requires
+    // `nested_filter::OnlyBodies` or equivalent.
+    #[rustfmt::skip]
+    let _const_block_inside_anon_const =
+        [
+            0
+            ;
+            7
+            +
+            const
+            {
+                3
+            }
+        ]
+        ;
+
+    black_box(());
 }
diff --git a/tests/crashes/103899.rs b/tests/crashes/103899.rs
deleted file mode 100644
index 39c2d72bd35..00000000000
--- a/tests/crashes/103899.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//@ known-bug: #103899
-
-trait BaseWithAssoc {
-    type Assoc;
-}
-
-trait WrapperWithAssoc {
-    type BaseAssoc: BaseWithAssoc;
-}
-
-struct Wrapper<B> {
-    inner: B,
-}
-
-struct ProjectToBase<T: BaseWithAssoc> {
-    data_type_h: T::Assoc,
-}
-
-struct DoubleProject<L: WrapperWithAssoc> {
-    buffer: Wrapper<ProjectToBase<L::BaseAssoc>>,
-}
-
-fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
-    loop {}
-}
-
-fn main() {}
diff --git a/tests/crashes/105299.rs b/tests/crashes/105299.rs
deleted file mode 100644
index 8e3aafa47bc..00000000000
--- a/tests/crashes/105299.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//@ known-bug: #105299
-
-pub trait Foo: Clone {}
-
-pub struct Bar<'a, T: Clone> {
-    pub cow: std::borrow::Cow<'a, [T]>,
-
-    pub THIS_CAUSES_ICE: (), // #1
-}
-
-impl<T> Bar<'_, T>
-where
-    T: Clone,
-    [T]: Foo,
-{
-    pub fn MOVES_SELF(self) {} // #2
-}
-
-pub fn main() {}
diff --git a/tests/crashes/project-to-simd-array-field.rs b/tests/crashes/project-to-simd-array-field.rs
new file mode 100644
index 00000000000..6dc916c41db
--- /dev/null
+++ b/tests/crashes/project-to-simd-array-field.rs
@@ -0,0 +1,33 @@
+//@ known-bug: #137108
+//@compile-flags: -Copt-level=3
+
+// If you fix this, put it in the corresponding codegen test,
+// not in a UI test like the readme says.
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, core_intrinsics)]
+
+#[allow(non_camel_case_types)]
+#[derive(Clone, Copy)]
+#[repr(simd)]
+struct i32x3([i32; 3]);
+
+const _: () = { assert!(size_of::<i32x3>() == 16) };
+
+#[inline(always)]
+fn to_array3(a: i32x3) -> [i32; 3] {
+    a.0
+}
+
+// CHECK-LABEL: simd_add_self_then_return_array_packed(
+// CHECK-SAME: ptr{{.+}}sret{{.+}}%[[RET:.+]],
+// CHECK-SAME: ptr{{.+}}%a)
+#[no_mangle]
+pub fn simd_add_self_then_return_array_packed(a: i32x3) -> [i32; 3] {
+    // CHECK: %[[T1:.+]] = load <3 x i32>, ptr %a
+    // CHECK: %[[T2:.+]] = shl <3 x i32> %[[T1]], <i32 1, i32 1, i32 1>
+    // CHECK: store <3 x i32> %[[T2]], ptr %[[RET]]
+    let b = unsafe { core::intrinsics::simd::simd_add(a, a) };
+    to_array3(b)
+}
diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
index 727efe4b0d9..267a4c1cf6b 100644
--- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
+++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
@@ -47,6 +47,7 @@
 +         Deinit(_8);
 +         copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7);
 +         StorageDead(_4);
++         nop;
           StorageDead(_2);
 -         _0 = move _1;
 +         StorageLive(_12);
@@ -61,6 +62,7 @@
 +         Deinit(_16);
 +         copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15);
 +         StorageDead(_12);
++         nop;
           StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
index 8d0cd97f786..8e5c403cd7e 100644
--- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
+++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
@@ -47,6 +47,7 @@
 +         Deinit(_8);
 +         copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7);
 +         StorageDead(_4);
++         nop;
           StorageDead(_2);
 -         _0 = move _1;
 +         StorageLive(_12);
@@ -61,6 +62,7 @@
 +         Deinit(_16);
 +         copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15);
 +         StorageDead(_12);
++         nop;
           StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff
index 6d1e2a72fdb..96c5aadd85f 100644
--- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff
+++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff
@@ -47,6 +47,7 @@
 +         Deinit(_8);
 +         copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7);
 +         StorageDead(_4);
++         nop;
           StorageDead(_2);
 -         _0 = move _1;
 +         StorageLive(_12);
@@ -61,6 +62,7 @@
 +         Deinit(_16);
 +         copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15);
 +         StorageDead(_12);
++         nop;
           StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff
index 4b1406d0d62..d20e2e08eaa 100644
--- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff
+++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff
@@ -47,6 +47,7 @@
 +         Deinit(_8);
 +         copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7);
 +         StorageDead(_4);
++         nop;
           StorageDead(_2);
 -         _0 = move _1;
 +         StorageLive(_12);
@@ -61,6 +62,7 @@
 +         Deinit(_16);
 +         copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15);
 +         StorageDead(_12);
++         nop;
           StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index b7a9b4a1fe0..7ef532d222d 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -4,28 +4,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _21: std::option::Option<(usize, &T)>;
-    let mut _24: &impl Fn(usize, &T);
-    let mut _25: (usize, &T);
-    let _26: ();
+    let mut _11: std::ptr::NonNull<T>;
+    let mut _12: *const T;
+    let mut _13: usize;
+    let mut _32: std::option::Option<(usize, &T)>;
+    let mut _35: &impl Fn(usize, &T);
+    let mut _36: (usize, &T);
+    let _37: ();
     scope 1 {
-        debug iter => _13;
-        let _22: usize;
-        let _23: &T;
+        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
+        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
+        debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _13;
+        let _33: usize;
+        let _34: &T;
         scope 2 {
-            debug i => _22;
-            debug x => _23;
+            debug i => _33;
+            debug x => _34;
         }
         scope 19 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
-            let mut _15: std::option::Option<&T>;
-            let mut _19: (usize, bool);
-            let mut _20: (usize, &T);
+            let mut _27: std::option::Option<&T>;
+            let mut _30: (usize, bool);
+            let mut _31: (usize, &T);
             scope 20 {
-                let _18: usize;
+                let _29: usize;
                 scope 25 {
                 }
             }
@@ -40,11 +42,59 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 }
             }
             scope 26 (inlined <Option<&T> as Try>::branch) {
-                let mut _16: isize;
-                let _17: &T;
+                let _28: &T;
                 scope 27 {
                 }
             }
+            scope 29 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
+                let _14: std::ptr::NonNull<T>;
+                let _16: std::ptr::NonNull<T>;
+                let mut _19: bool;
+                let mut _22: std::ptr::NonNull<T>;
+                let mut _24: usize;
+                let _26: &T;
+                scope 30 {
+                    let _15: *const T;
+                    scope 31 {
+                        let _23: usize;
+                        scope 32 {
+                            scope 35 (inlined core::num::<impl usize>::unchecked_sub) {
+                                scope 36 (inlined core::ub_checks::check_language_ub) {
+                                    scope 37 (inlined core::ub_checks::check_language_ub::runtime) {
+                                    }
+                                }
+                            }
+                            scope 38 (inlined without_provenance_mut::<T>) {
+                            }
+                        }
+                        scope 33 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
+                            scope 34 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
+                            }
+                        }
+                        scope 39 (inlined <NonNull<T> as PartialEq>::eq) {
+                            let mut _17: *mut T;
+                            let mut _18: *mut T;
+                            scope 40 (inlined NonNull::<T>::as_ptr) {
+                            }
+                            scope 41 (inlined NonNull::<T>::as_ptr) {
+                            }
+                        }
+                        scope 42 (inlined NonNull::<T>::add) {
+                            let mut _20: *const T;
+                            let mut _21: *const T;
+                            scope 43 (inlined NonNull::<T>::as_ptr) {
+                            }
+                        }
+                        scope 44 (inlined NonNull::<T>::as_ref::<'_>) {
+                            let _25: *const T;
+                            scope 45 (inlined NonNull::<T>::as_ptr) {
+                            }
+                            scope 46 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -89,9 +139,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
         StorageLive(_3);
-        StorageLive(_6);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -120,86 +168,150 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
         _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
         StorageDead(_9);
         StorageDead(_4);
-        StorageDead(_6);
         StorageDead(_3);
-        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
-        StorageDead(_11);
+        StorageLive(_11);
+        StorageLive(_12);
         StorageLive(_13);
-        _13 = copy _12;
+        _11 = copy _6;
+        _12 = copy _10;
+        _13 = const 0_usize;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_21);
-        StorageLive(_18);
-        StorageLive(_19);
-        StorageLive(_15);
+        StorageLive(_32);
+        StorageLive(_29);
+        StorageLive(_30);
+        StorageLive(_27);
         StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as Iterator>::next(move _14) -> [return: bb5, unwind unreachable];
+        StorageLive(_15);
+        StorageLive(_23);
+        StorageLive(_24);
+        StorageLive(_16);
+        StorageLive(_26);
+        _14 = copy _11;
+        _15 = copy _12;
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        StorageDead(_14);
-        StorageLive(_16);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageLive(_19);
+        _16 = copy _15 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_17);
+        _17 = copy _14 as *mut T (Transmute);
+        StorageLive(_18);
+        _18 = copy _16 as *mut T (Transmute);
+        _19 = Eq(move _17, move _18);
+        StorageDead(_18);
+        StorageDead(_17);
+        switchInt(move _19) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_15);
         StorageDead(_19);
-        StorageDead(_18);
+        StorageLive(_22);
+        StorageLive(_21);
+        StorageLive(_20);
+        _20 = copy _14 as *const T (Transmute);
+        _21 = Offset(move _20, const 1_usize);
+        StorageDead(_20);
+        _22 = NonNull::<T> { pointer: move _21 };
         StorageDead(_21);
-        StorageDead(_13);
-        drop(_2) -> [return: bb7, unwind unreachable];
+        _11 = move _22;
+        StorageDead(_22);
+        goto -> bb13;
     }
 
     bb7: {
-        return;
+        StorageDead(_19);
+        StorageDead(_26);
+        StorageDead(_16);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_15);
+        StorageDead(_14);
+        goto -> bb10;
     }
 
     bb8: {
-        _17 = move ((_15 as Some).0: &T);
-        StorageDead(_16);
-        StorageDead(_15);
-        _18 = copy (_13.1: usize);
-        _19 = AddWithOverflow(copy (_13.1: usize), const 1_usize);
-        assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_13.1: usize), const 1_usize) -> [success: bb9, unwind unreachable];
+        _23 = copy _15 as usize (Transmute);
+        switchInt(copy _23) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        (_13.1: usize) = move (_19.0: usize);
-        StorageLive(_20);
-        _20 = (copy _18, copy _17);
-        _21 = Option::<(usize, &T)>::Some(move _20);
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_18);
-        _22 = copy (((_21 as Some).0: (usize, &T)).0: usize);
-        _23 = copy (((_21 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_24);
-        _24 = &_2;
-        StorageLive(_25);
-        _25 = (copy _22, copy _23);
-        _26 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _24, move _25) -> [return: bb10, unwind unreachable];
+        StorageDead(_26);
+        StorageDead(_16);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_15);
+        StorageDead(_14);
+        goto -> bb10;
     }
 
     bb10: {
+        StorageDead(_27);
+        StorageDead(_30);
+        StorageDead(_29);
+        StorageDead(_32);
+        StorageDead(_11);
+        StorageDead(_12);
+        StorageDead(_13);
+        drop(_2) -> [return: bb11, unwind unreachable];
+    }
+
+    bb11: {
+        return;
+    }
+
+    bb12: {
+        _24 = SubUnchecked(copy _23, const 1_usize);
+        _12 = copy _24 as *const T (Transmute);
+        goto -> bb13;
+    }
+
+    bb13: {
+        StorageLive(_25);
+        _25 = copy _14 as *const T (Transmute);
+        _26 = &(*_25);
         StorageDead(_25);
+        _27 = Option::<&T>::Some(copy _26);
+        StorageDead(_26);
+        StorageDead(_16);
         StorageDead(_24);
-        StorageDead(_21);
-        goto -> bb4;
+        StorageDead(_23);
+        StorageDead(_15);
+        StorageDead(_14);
+        _28 = move ((_27 as Some).0: &T);
+        StorageDead(_27);
+        _29 = copy _13;
+        _30 = AddWithOverflow(copy _13, const 1_usize);
+        assert(!move (_30.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _13, const 1_usize) -> [success: bb14, unwind unreachable];
     }
 
-    bb11: {
-        unreachable;
+    bb14: {
+        _13 = move (_30.0: usize);
+        StorageLive(_31);
+        _31 = (copy _29, copy _28);
+        _32 = Option::<(usize, &T)>::Some(move _31);
+        StorageDead(_31);
+        StorageDead(_30);
+        StorageDead(_29);
+        _33 = copy (((_32 as Some).0: (usize, &T)).0: usize);
+        _34 = copy (((_32 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_35);
+        _35 = &_2;
+        StorageLive(_36);
+        _36 = (copy _33, copy _34);
+        _37 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _35, move _36) -> [return: bb15, unwind unreachable];
+    }
+
+    bb15: {
+        StorageDead(_36);
+        StorageDead(_35);
+        StorageDead(_32);
+        goto -> bb4;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index dc13bb23c31..62787f3447c 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -4,19 +4,68 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: &mut std::slice::Iter<'_, T>;
-    let mut _14: std::option::Option<&T>;
-    let mut _15: isize;
-    let mut _17: &impl Fn(&T);
-    let mut _18: (&T,);
-    let _19: ();
+    let mut _11: std::ptr::NonNull<T>;
+    let mut _12: *const T;
+    let mut _26: std::option::Option<&T>;
+    let mut _28: &impl Fn(&T);
+    let mut _29: (&T,);
+    let _30: ();
     scope 1 {
-        debug iter => _12;
-        let _16: &T;
+        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
+        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
+        let _27: &T;
         scope 2 {
-            debug x => _16;
+            debug x => _27;
+        }
+        scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
+            let _13: std::ptr::NonNull<T>;
+            let _15: std::ptr::NonNull<T>;
+            let mut _18: bool;
+            let mut _21: std::ptr::NonNull<T>;
+            let mut _23: usize;
+            let _25: &T;
+            scope 18 {
+                let _14: *const T;
+                scope 19 {
+                    let _22: usize;
+                    scope 20 {
+                        scope 23 (inlined core::num::<impl usize>::unchecked_sub) {
+                            scope 24 (inlined core::ub_checks::check_language_ub) {
+                                scope 25 (inlined core::ub_checks::check_language_ub::runtime) {
+                                }
+                            }
+                        }
+                        scope 26 (inlined without_provenance_mut::<T>) {
+                        }
+                    }
+                    scope 21 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
+                        scope 22 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
+                        }
+                    }
+                    scope 27 (inlined <NonNull<T> as PartialEq>::eq) {
+                        let mut _16: *mut T;
+                        let mut _17: *mut T;
+                        scope 28 (inlined NonNull::<T>::as_ptr) {
+                        }
+                        scope 29 (inlined NonNull::<T>::as_ptr) {
+                        }
+                    }
+                    scope 30 (inlined NonNull::<T>::add) {
+                        let mut _19: *const T;
+                        let mut _20: *const T;
+                        scope 31 (inlined NonNull::<T>::as_ptr) {
+                        }
+                    }
+                    scope 32 (inlined NonNull::<T>::as_ref::<'_>) {
+                        let _24: *const T;
+                        scope 33 (inlined NonNull::<T>::as_ptr) {
+                        }
+                        scope 34 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
+                        }
+                    }
+                }
+            }
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -58,7 +107,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_6);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -87,57 +135,125 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
         _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
         StorageDead(_9);
         StorageDead(_4);
-        StorageDead(_6);
         StorageDead(_3);
+        StorageLive(_11);
         StorageLive(_12);
-        _12 = copy _11;
+        _11 = copy _6;
+        _12 = copy _10;
         goto -> bb4;
     }
 
     bb4: {
+        StorageLive(_26);
+        StorageLive(_13);
         StorageLive(_14);
-        _13 = &mut _12;
-        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
+        StorageLive(_22);
+        StorageLive(_23);
+        StorageLive(_15);
+        StorageLive(_25);
+        _13 = copy _11;
+        _14 = copy _12;
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        _15 = discriminant(_14);
-        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageLive(_18);
+        _15 = copy _14 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_16);
+        _16 = copy _13 as *mut T (Transmute);
+        StorageLive(_17);
+        _17 = copy _15 as *mut T (Transmute);
+        _18 = Eq(move _16, move _17);
+        StorageDead(_17);
+        StorageDead(_16);
+        switchInt(move _18) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_14);
-        StorageDead(_12);
-        drop(_2) -> [return: bb7, unwind unreachable];
+        StorageDead(_18);
+        StorageLive(_21);
+        StorageLive(_20);
+        StorageLive(_19);
+        _19 = copy _13 as *const T (Transmute);
+        _20 = Offset(move _19, const 1_usize);
+        StorageDead(_19);
+        _21 = NonNull::<T> { pointer: move _20 };
+        StorageDead(_20);
+        _11 = move _21;
+        StorageDead(_21);
+        goto -> bb13;
     }
 
     bb7: {
-        return;
+        StorageDead(_18);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
+        StorageDead(_14);
+        StorageDead(_13);
+        goto -> bb10;
     }
 
     bb8: {
-        _16 = copy ((_14 as Some).0: &T);
-        StorageLive(_17);
-        _17 = &_2;
-        StorageLive(_18);
-        _18 = (copy _16,);
-        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable];
+        _22 = copy _14 as usize (Transmute);
+        switchInt(copy _22) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        StorageDead(_18);
-        StorageDead(_17);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
         StorageDead(_14);
-        goto -> bb4;
+        StorageDead(_13);
+        goto -> bb10;
     }
 
     bb10: {
-        unreachable;
+        StorageDead(_26);
+        StorageDead(_11);
+        StorageDead(_12);
+        drop(_2) -> [return: bb11, unwind unreachable];
+    }
+
+    bb11: {
+        return;
+    }
+
+    bb12: {
+        _23 = SubUnchecked(copy _22, const 1_usize);
+        _12 = copy _23 as *const T (Transmute);
+        goto -> bb13;
+    }
+
+    bb13: {
+        StorageLive(_24);
+        _24 = copy _13 as *const T (Transmute);
+        _25 = &(*_24);
+        StorageDead(_24);
+        _26 = Option::<&T>::Some(copy _25);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
+        StorageDead(_14);
+        StorageDead(_13);
+        _27 = copy ((_26 as Some).0: &T);
+        StorageLive(_28);
+        _28 = &_2;
+        StorageLive(_29);
+        _29 = (copy _27,);
+        _30 = <impl Fn(&T) as Fn<(&T,)>>::call(move _28, move _29) -> [return: bb14, unwind unreachable];
+    }
+
+    bb14: {
+        StorageDead(_29);
+        StorageDead(_28);
+        StorageDead(_26);
+        goto -> bb4;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 3f1e0e0f746..e5478e27918 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -4,19 +4,68 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: &mut std::slice::Iter<'_, T>;
-    let mut _14: std::option::Option<&T>;
-    let mut _15: isize;
-    let mut _17: &impl Fn(&T);
-    let mut _18: (&T,);
-    let _19: ();
+    let mut _11: std::ptr::NonNull<T>;
+    let mut _12: *const T;
+    let mut _26: std::option::Option<&T>;
+    let mut _28: &impl Fn(&T);
+    let mut _29: (&T,);
+    let _30: ();
     scope 1 {
-        debug iter => _12;
-        let _16: &T;
+        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
+        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
+        let _27: &T;
         scope 2 {
-            debug x => _16;
+            debug x => _27;
+        }
+        scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
+            let _13: std::ptr::NonNull<T>;
+            let _15: std::ptr::NonNull<T>;
+            let mut _18: bool;
+            let mut _21: std::ptr::NonNull<T>;
+            let mut _23: usize;
+            let _25: &T;
+            scope 18 {
+                let _14: *const T;
+                scope 19 {
+                    let _22: usize;
+                    scope 20 {
+                        scope 23 (inlined core::num::<impl usize>::unchecked_sub) {
+                            scope 24 (inlined core::ub_checks::check_language_ub) {
+                                scope 25 (inlined core::ub_checks::check_language_ub::runtime) {
+                                }
+                            }
+                        }
+                        scope 26 (inlined without_provenance_mut::<T>) {
+                        }
+                    }
+                    scope 21 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
+                        scope 22 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
+                        }
+                    }
+                    scope 27 (inlined <NonNull<T> as PartialEq>::eq) {
+                        let mut _16: *mut T;
+                        let mut _17: *mut T;
+                        scope 28 (inlined NonNull::<T>::as_ptr) {
+                        }
+                        scope 29 (inlined NonNull::<T>::as_ptr) {
+                        }
+                    }
+                    scope 30 (inlined NonNull::<T>::add) {
+                        let mut _19: *const T;
+                        let mut _20: *const T;
+                        scope 31 (inlined NonNull::<T>::as_ptr) {
+                        }
+                    }
+                    scope 32 (inlined NonNull::<T>::as_ref::<'_>) {
+                        let _24: *const T;
+                        scope 33 (inlined NonNull::<T>::as_ptr) {
+                        }
+                        scope 34 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
+                        }
+                    }
+                }
+            }
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -58,7 +107,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_6);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -87,65 +135,133 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
         _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
         StorageDead(_9);
         StorageDead(_4);
-        StorageDead(_6);
         StorageDead(_3);
+        StorageLive(_11);
         StorageLive(_12);
-        _12 = copy _11;
+        _11 = copy _6;
+        _12 = copy _10;
         goto -> bb4;
     }
 
     bb4: {
+        StorageLive(_26);
+        StorageLive(_13);
         StorageLive(_14);
-        _13 = &mut _12;
-        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
+        StorageLive(_22);
+        StorageLive(_23);
+        StorageLive(_15);
+        StorageLive(_25);
+        _13 = copy _11;
+        _14 = copy _12;
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        _15 = discriminant(_14);
-        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageLive(_18);
+        _15 = copy _14 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_16);
+        _16 = copy _13 as *mut T (Transmute);
+        StorageLive(_17);
+        _17 = copy _15 as *mut T (Transmute);
+        _18 = Eq(move _16, move _17);
+        StorageDead(_17);
+        StorageDead(_16);
+        switchInt(move _18) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_14);
-        StorageDead(_12);
-        drop(_2) -> [return: bb7, unwind continue];
+        StorageDead(_18);
+        StorageLive(_21);
+        StorageLive(_20);
+        StorageLive(_19);
+        _19 = copy _13 as *const T (Transmute);
+        _20 = Offset(move _19, const 1_usize);
+        StorageDead(_19);
+        _21 = NonNull::<T> { pointer: move _20 };
+        StorageDead(_20);
+        _11 = move _21;
+        StorageDead(_21);
+        goto -> bb13;
     }
 
     bb7: {
-        return;
+        StorageDead(_18);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
+        StorageDead(_14);
+        StorageDead(_13);
+        goto -> bb10;
     }
 
     bb8: {
-        _16 = copy ((_14 as Some).0: &T);
-        StorageLive(_17);
-        _17 = &_2;
-        StorageLive(_18);
-        _18 = (copy _16,);
-        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11];
+        _22 = copy _14 as usize (Transmute);
+        switchInt(copy _22) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        StorageDead(_18);
-        StorageDead(_17);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
         StorageDead(_14);
-        goto -> bb4;
+        StorageDead(_13);
+        goto -> bb10;
     }
 
     bb10: {
-        unreachable;
+        StorageDead(_26);
+        StorageDead(_11);
+        StorageDead(_12);
+        drop(_2) -> [return: bb11, unwind continue];
+    }
+
+    bb11: {
+        return;
+    }
+
+    bb12: {
+        _23 = SubUnchecked(copy _22, const 1_usize);
+        _12 = copy _23 as *const T (Transmute);
+        goto -> bb13;
+    }
+
+    bb13: {
+        StorageLive(_24);
+        _24 = copy _13 as *const T (Transmute);
+        _25 = &(*_24);
+        StorageDead(_24);
+        _26 = Option::<&T>::Some(copy _25);
+        StorageDead(_25);
+        StorageDead(_15);
+        StorageDead(_23);
+        StorageDead(_22);
+        StorageDead(_14);
+        StorageDead(_13);
+        _27 = copy ((_26 as Some).0: &T);
+        StorageLive(_28);
+        _28 = &_2;
+        StorageLive(_29);
+        _29 = (copy _27,);
+        _30 = <impl Fn(&T) as Fn<(&T,)>>::call(move _28, move _29) -> [return: bb14, unwind: bb15];
+    }
+
+    bb14: {
+        StorageDead(_29);
+        StorageDead(_28);
+        StorageDead(_26);
+        goto -> bb4;
     }
 
-    bb11 (cleanup): {
-        drop(_2) -> [return: bb12, unwind terminate(cleanup)];
+    bb15 (cleanup): {
+        drop(_2) -> [return: bb16, unwind terminate(cleanup)];
     }
 
-    bb12 (cleanup): {
+    bb16 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
index 8edac638ccd..b6df2300efb 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
@@ -3,12 +3,134 @@
 fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> {
     debug it => _1;
     let mut _0: std::option::Option<&T>;
+    scope 1 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
+        let _2: std::ptr::NonNull<T>;
+        let _4: std::ptr::NonNull<T>;
+        let mut _7: bool;
+        let mut _10: std::ptr::NonNull<T>;
+        let mut _12: usize;
+        let _14: &T;
+        scope 2 {
+            let _3: *const T;
+            scope 3 {
+                let _11: usize;
+                scope 4 {
+                    scope 7 (inlined core::num::<impl usize>::unchecked_sub) {
+                        scope 8 (inlined core::ub_checks::check_language_ub) {
+                            scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                    }
+                    scope 10 (inlined without_provenance_mut::<T>) {
+                    }
+                }
+                scope 5 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
+                    scope 6 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
+                    }
+                }
+                scope 11 (inlined <NonNull<T> as PartialEq>::eq) {
+                    let mut _5: *mut T;
+                    let mut _6: *mut T;
+                    scope 12 (inlined NonNull::<T>::as_ptr) {
+                    }
+                    scope 13 (inlined NonNull::<T>::as_ptr) {
+                    }
+                }
+                scope 14 (inlined NonNull::<T>::add) {
+                    let mut _8: *const T;
+                    let mut _9: *const T;
+                    scope 15 (inlined NonNull::<T>::as_ptr) {
+                    }
+                }
+                scope 16 (inlined NonNull::<T>::as_ref::<'_>) {
+                    let _13: *const T;
+                    scope 17 (inlined NonNull::<T>::as_ptr) {
+                    }
+                    scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
+                    }
+                }
+            }
+        }
+    }
 
     bb0: {
-        _0 = <std::slice::Iter<'_, T> as Iterator>::next(move _1) -> [return: bb1, unwind unreachable];
+        StorageLive(_2);
+        StorageLive(_3);
+        StorageLive(_11);
+        StorageLive(_12);
+        StorageLive(_4);
+        StorageLive(_14);
+        _2 = copy ((*_1).0: std::ptr::NonNull<T>);
+        _3 = copy ((*_1).1: *const T);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb4];
     }
 
     bb1: {
+        StorageLive(_7);
+        _4 = copy _3 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_5);
+        _5 = copy _2 as *mut T (Transmute);
+        StorageLive(_6);
+        _6 = copy _4 as *mut T (Transmute);
+        _7 = Eq(move _5, move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        switchInt(move _7) -> [0: bb2, otherwise: bb3];
+    }
+
+    bb2: {
+        StorageDead(_7);
+        StorageLive(_10);
+        StorageLive(_9);
+        StorageLive(_8);
+        _8 = copy _2 as *const T (Transmute);
+        _9 = Offset(move _8, const 1_usize);
+        StorageDead(_8);
+        _10 = NonNull::<T> { pointer: move _9 };
+        StorageDead(_9);
+        ((*_1).0: std::ptr::NonNull<T>) = move _10;
+        StorageDead(_10);
+        goto -> bb7;
+    }
+
+    bb3: {
+        _0 = const {transmute(0x0000000000000000): Option<&T>};
+        StorageDead(_7);
+        goto -> bb8;
+    }
+
+    bb4: {
+        _11 = copy _3 as usize (Transmute);
+        switchInt(copy _11) -> [0: bb5, otherwise: bb6];
+    }
+
+    bb5: {
+        _0 = const {transmute(0x0000000000000000): Option<&T>};
+        goto -> bb8;
+    }
+
+    bb6: {
+        _12 = SubUnchecked(copy _11, const 1_usize);
+        ((*_1).1: *const T) = copy _12 as *const T (Transmute);
+        goto -> bb7;
+    }
+
+    bb7: {
+        StorageLive(_13);
+        _13 = copy _2 as *const T (Transmute);
+        _14 = &(*_13);
+        StorageDead(_13);
+        _0 = Option::<&T>::Some(copy _14);
+        goto -> bb8;
+    }
+
+    bb8: {
+        StorageDead(_14);
+        StorageDead(_4);
+        StorageDead(_12);
+        StorageDead(_11);
+        StorageDead(_3);
+        StorageDead(_2);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
index fdde0717343..b6df2300efb 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
@@ -3,12 +3,134 @@
 fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> {
     debug it => _1;
     let mut _0: std::option::Option<&T>;
+    scope 1 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
+        let _2: std::ptr::NonNull<T>;
+        let _4: std::ptr::NonNull<T>;
+        let mut _7: bool;
+        let mut _10: std::ptr::NonNull<T>;
+        let mut _12: usize;
+        let _14: &T;
+        scope 2 {
+            let _3: *const T;
+            scope 3 {
+                let _11: usize;
+                scope 4 {
+                    scope 7 (inlined core::num::<impl usize>::unchecked_sub) {
+                        scope 8 (inlined core::ub_checks::check_language_ub) {
+                            scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                    }
+                    scope 10 (inlined without_provenance_mut::<T>) {
+                    }
+                }
+                scope 5 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
+                    scope 6 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
+                    }
+                }
+                scope 11 (inlined <NonNull<T> as PartialEq>::eq) {
+                    let mut _5: *mut T;
+                    let mut _6: *mut T;
+                    scope 12 (inlined NonNull::<T>::as_ptr) {
+                    }
+                    scope 13 (inlined NonNull::<T>::as_ptr) {
+                    }
+                }
+                scope 14 (inlined NonNull::<T>::add) {
+                    let mut _8: *const T;
+                    let mut _9: *const T;
+                    scope 15 (inlined NonNull::<T>::as_ptr) {
+                    }
+                }
+                scope 16 (inlined NonNull::<T>::as_ref::<'_>) {
+                    let _13: *const T;
+                    scope 17 (inlined NonNull::<T>::as_ptr) {
+                    }
+                    scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
+                    }
+                }
+            }
+        }
+    }
 
     bb0: {
-        _0 = <std::slice::Iter<'_, T> as Iterator>::next(move _1) -> [return: bb1, unwind continue];
+        StorageLive(_2);
+        StorageLive(_3);
+        StorageLive(_11);
+        StorageLive(_12);
+        StorageLive(_4);
+        StorageLive(_14);
+        _2 = copy ((*_1).0: std::ptr::NonNull<T>);
+        _3 = copy ((*_1).1: *const T);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb4];
     }
 
     bb1: {
+        StorageLive(_7);
+        _4 = copy _3 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_5);
+        _5 = copy _2 as *mut T (Transmute);
+        StorageLive(_6);
+        _6 = copy _4 as *mut T (Transmute);
+        _7 = Eq(move _5, move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        switchInt(move _7) -> [0: bb2, otherwise: bb3];
+    }
+
+    bb2: {
+        StorageDead(_7);
+        StorageLive(_10);
+        StorageLive(_9);
+        StorageLive(_8);
+        _8 = copy _2 as *const T (Transmute);
+        _9 = Offset(move _8, const 1_usize);
+        StorageDead(_8);
+        _10 = NonNull::<T> { pointer: move _9 };
+        StorageDead(_9);
+        ((*_1).0: std::ptr::NonNull<T>) = move _10;
+        StorageDead(_10);
+        goto -> bb7;
+    }
+
+    bb3: {
+        _0 = const {transmute(0x0000000000000000): Option<&T>};
+        StorageDead(_7);
+        goto -> bb8;
+    }
+
+    bb4: {
+        _11 = copy _3 as usize (Transmute);
+        switchInt(copy _11) -> [0: bb5, otherwise: bb6];
+    }
+
+    bb5: {
+        _0 = const {transmute(0x0000000000000000): Option<&T>};
+        goto -> bb8;
+    }
+
+    bb6: {
+        _12 = SubUnchecked(copy _11, const 1_usize);
+        ((*_1).1: *const T) = copy _12 as *const T (Transmute);
+        goto -> bb7;
+    }
+
+    bb7: {
+        StorageLive(_13);
+        _13 = copy _2 as *const T (Transmute);
+        _14 = &(*_13);
+        StorageDead(_13);
+        _0 = Option::<&T>::Some(copy _14);
+        goto -> bb8;
+    }
+
+    bb8: {
+        StorageDead(_14);
+        StorageDead(_4);
+        StorageDead(_12);
+        StorageDead(_11);
+        StorageDead(_3);
+        StorageDead(_2);
         return;
     }
 }
diff --git a/tests/run-make/avr-rjmp-offset/rmake.rs b/tests/run-make/avr-rjmp-offset/rmake.rs
index de64b724eed..da314f26ca7 100644
--- a/tests/run-make/avr-rjmp-offset/rmake.rs
+++ b/tests/run-make/avr-rjmp-offset/rmake.rs
@@ -22,7 +22,12 @@ fn main() {
         .input("avr-rjmp-offsets.rs")
         .opt_level("s")
         .panic("abort")
-        .target("avr-unknown-gnu-atmega328")
+        .target("avr-none")
+        // rust-lld has some troubles understanding the -mmcu flag, so for the
+        // time being let's tell rustc to emit binary that's compatible with the
+        // target CPU that lld defaults to, i.e. just `avr` (that's simply the
+        // minimal common instruction set across all AVRs)
+        .target_cpu("avr")
         // normally one links with `avr-gcc`, but this is not available in CI,
         // hence this test diverges from the default behavior to enable linking
         // at all, which is necessary for the test (to resolve the labels). To
@@ -49,6 +54,7 @@ fn main() {
     // of the Rust compiler did produce a label `rjmp .-4` (misses the first
     // instruction in the loop).
     assert!(disassembly.contains("<main>"), "no main function in output");
+
     disassembly
         .trim()
         .lines()
diff --git a/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml b/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml
new file mode 100644
index 00000000000..f09f0971351
--- /dev/null
+++ b/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml
@@ -0,0 +1,15 @@
+// Checks sidebar resizing close the Settings popover
+go-to: "file://" + |DOC_PATH| + "/test_docs/SidebarSort/trait.Sort.html#foreign-impls"
+
+// Check that the sidebar contains the expected foreign implementations
+assert-text: (".sidebar-elems section ul > li:nth-child(1)", "&'a str")
+assert-text: (".sidebar-elems section ul > li:nth-child(2)", "AtomicBool")
+assert-text: (".sidebar-elems section ul > li:nth-child(3)", "AtomicU8")
+assert-text: (".sidebar-elems section ul > li:nth-child(4)", "AtomicU16")
+assert-text: (".sidebar-elems section ul > li:nth-child(5)", "AtomicU32")
+assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Cell<u8>")
+assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Cell<u16>")
+assert-text: (".sidebar-elems section ul > li:nth-child(8)", "u8")
+assert-text: (".sidebar-elems section ul > li:nth-child(9)", "u16")
+assert-text: (".sidebar-elems section ul > li:nth-child(10)", "u32")
+assert-text: (".sidebar-elems section ul > li:nth-child(11)", "usize")
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 1a9ffbe8898..f9c20ab22b8 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -713,3 +713,21 @@ pub trait ItemsTrait {
     /// blablala
     fn bar();
 }
+
+pub mod SidebarSort {
+    use std::cell::Cell;
+    use std::sync::atomic::*;
+    pub trait Sort {}
+
+    impl Sort for u32 {}
+    impl Sort for u8 {}
+    impl Sort for u16 {}
+    impl Sort for usize {}
+    impl Sort for AtomicU32 {}
+    impl Sort for AtomicU16 {}
+    impl Sort for AtomicU8 {}
+    impl Sort for AtomicBool {}
+    impl Sort for Cell<u16> {}
+    impl Sort for Cell<u8> {}
+    impl<'a> Sort for &'a str {}
+}
diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr
index c8f7d0a517c..57cc48aa9cf 100644
--- a/tests/ui/abi/c-zst.aarch64-darwin.stderr
+++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index 1015f7d8898..67380176730 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index 1015f7d8898..67380176730 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index 1015f7d8898..67380176730 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr
index c8f7d0a517c..57cc48aa9cf 100644
--- a/tests/ui/abi/c-zst.x86_64-linux.stderr
+++ b/tests/ui/abi/c-zst.x86_64-linux.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index 1015f7d8898..67380176730 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index e550e5bfcf3..5f73ff7d6bd 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -20,6 +20,7 @@ error: fn_abi_of(test) = FnAbi {
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -67,6 +68,7 @@ error: fn_abi_of(test) = FnAbi {
                                valid_range: 0..=1,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -125,6 +127,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                                    valid_range: 0..=1,
                                },
                            ),
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -163,6 +166,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                        ),
                        fields: Primitive,
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -213,6 +217,7 @@ error: fn_abi_of(test_generic) = FnAbi {
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -248,6 +253,7 @@ error: fn_abi_of(test_generic) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -297,6 +303,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -332,6 +339,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -369,6 +377,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -404,6 +413,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -444,6 +454,7 @@ error: ABIs are not compatible
                                count: 32,
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -483,6 +494,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -517,6 +529,7 @@ error: ABIs are not compatible
                                count: 32,
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -556,6 +569,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -598,6 +612,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -633,6 +648,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -670,6 +686,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -705,6 +722,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -748,6 +766,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -783,6 +802,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -820,6 +840,7 @@ error: ABIs are not compatible
                            ),
                            fields: Primitive,
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -855,6 +876,7 @@ error: ABIs are not compatible
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -923,6 +945,7 @@ error: fn_abi_of(assoc_test) = FnAbi {
                                    valid_range: $NON_NULL,
                                },
                            ),
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -960,6 +983,7 @@ error: fn_abi_of(assoc_test) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr
index 781e9b2f4c9..ec85030c106 100644
--- a/tests/ui/abi/sysv64-zst.stderr
+++ b/tests/ui/abi/sysv64-zst.stderr
@@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                memory_index: [],
                            },
                            largest_niche: None,
+                           uninhabited: false,
                            variants: Single {
                                index: 0,
                            },
@@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
index 28e7975c7a2..305fbbd275f 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
-  --> $DIR/as_expression.rs:55:15
+  --> $DIR/as_expression.rs:56:15
    |
 LL |     SelectInt.check("bar");
    |               ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index 4f685c508c7..90bb715a052 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
-  --> $DIR/as_expression.rs:55:21
+  --> $DIR/as_expression.rs:56:21
    |
 LL |     SelectInt.check("bar");
    |               ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
@@ -8,7 +8,7 @@ LL |     SelectInt.check("bar");
    |
    = help: the trait `AsExpression<Text>` is implemented for `&str`
 note: required by a bound in `Foo::check`
-  --> $DIR/as_expression.rs:46:12
+  --> $DIR/as_expression.rs:47:12
    |
 LL |     fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
    |        ----- required by a bound in this associated function
@@ -17,7 +17,7 @@ LL |         T: AsExpression<Self::SqlType>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
 
 error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
-  --> $DIR/as_expression.rs:55:5
+  --> $DIR/as_expression.rs:56:5
    |
 LL |     SelectInt.check("bar");
    |     ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
index 48c1ed2b02d..73a238ddf50 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 pub trait Expression {
     type SqlType;
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr
index 47597a5d405..8a478a5c733 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:10:1
+  --> $DIR/does_not_acccept_args.rs:11:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:14:1
+  --> $DIR/does_not_acccept_args.rs:15:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:18:1
+  --> $DIR/does_not_acccept_args.rs:19:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted(42))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr
index 47597a5d405..8a478a5c733 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:10:1
+  --> $DIR/does_not_acccept_args.rs:11:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:14:1
+  --> $DIR/does_not_acccept_args.rs:15:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/does_not_acccept_args.rs:18:1
+  --> $DIR/does_not_acccept_args.rs:19:1
    |
 LL | #[diagnostic::do_not_recommend(not_accepted(42))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs
index eeff5e2e6e8..5c21c045e10 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs
@@ -2,6 +2,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.syntax
 
 trait Foo {}
 trait Bar {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr
index ee6ebabadd9..e348f0c8902 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:6:1
+  --> $DIR/incorrect-locations.rs:7:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,49 +7,49 @@ LL | #[diagnostic::do_not_recommend]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:10:1
+  --> $DIR/incorrect-locations.rs:11:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:14:1
+  --> $DIR/incorrect-locations.rs:15:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:18:1
+  --> $DIR/incorrect-locations.rs:19:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:22:1
+  --> $DIR/incorrect-locations.rs:23:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:26:1
+  --> $DIR/incorrect-locations.rs:27:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:30:1
+  --> $DIR/incorrect-locations.rs:31:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:34:1
+  --> $DIR/incorrect-locations.rs:35:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:38:1
+  --> $DIR/incorrect-locations.rs:39:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr
index ee6ebabadd9..e348f0c8902 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:6:1
+  --> $DIR/incorrect-locations.rs:7:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,49 +7,49 @@ LL | #[diagnostic::do_not_recommend]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:10:1
+  --> $DIR/incorrect-locations.rs:11:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:14:1
+  --> $DIR/incorrect-locations.rs:15:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:18:1
+  --> $DIR/incorrect-locations.rs:19:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:22:1
+  --> $DIR/incorrect-locations.rs:23:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:26:1
+  --> $DIR/incorrect-locations.rs:27:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:30:1
+  --> $DIR/incorrect-locations.rs:31:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:34:1
+  --> $DIR/incorrect-locations.rs:35:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
-  --> $DIR/incorrect-locations.rs:38:1
+  --> $DIR/incorrect-locations.rs:39:1
    |
 LL | #[diagnostic::do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs
index 1cf436aa2af..e716457eaed 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs
@@ -2,6 +2,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.allowed-positions
 
 #[diagnostic::do_not_recommend]
 //~^WARN `#[diagnostic::do_not_recommend]` can only be placed
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr
index b14c68d6897..cb1da8ff8be 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `(): Root` is not satisfied
-  --> $DIR/nested.rs:21:18
+  --> $DIR/nested.rs:22:18
    |
 LL |     needs_root::<()>();
    |                  ^^ the trait `Root` is not implemented for `()`
    |
 note: required by a bound in `needs_root`
-  --> $DIR/nested.rs:18:18
+  --> $DIR/nested.rs:19:18
    |
 LL | fn needs_root<T: Root>() {}
    |                  ^^^^ required by this bound in `needs_root`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr
index b14c68d6897..cb1da8ff8be 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `(): Root` is not satisfied
-  --> $DIR/nested.rs:21:18
+  --> $DIR/nested.rs:22:18
    |
 LL |     needs_root::<()>();
    |                  ^^ the trait `Root` is not implemented for `()`
    |
 note: required by a bound in `needs_root`
-  --> $DIR/nested.rs:18:18
+  --> $DIR/nested.rs:19:18
    |
 LL | fn needs_root<T: Root>() {}
    |                  ^^^^ required by this bound in `needs_root`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs
index 6534157d1fb..3c96c760dfb 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 trait Root {}
 trait DontRecommend {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
index 884b13c17b8..dd425f1e6ee 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `*mut (): Foo` is not satisfied
-  --> $DIR/simple.rs:15:17
+  --> $DIR/simple.rs:16:17
    |
 LL |     needs_foo::<*mut ()>();
    |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
    |
 note: required by a bound in `needs_foo`
-  --> $DIR/simple.rs:10:17
+  --> $DIR/simple.rs:11:17
    |
 LL | fn needs_foo<T: Foo>() {}
    |                 ^^^ required by this bound in `needs_foo`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
index 884b13c17b8..dd425f1e6ee 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `*mut (): Foo` is not satisfied
-  --> $DIR/simple.rs:15:17
+  --> $DIR/simple.rs:16:17
    |
 LL |     needs_foo::<*mut ()>();
    |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
    |
 note: required by a bound in `needs_foo`
-  --> $DIR/simple.rs:10:17
+  --> $DIR/simple.rs:11:17
    |
 LL | fn needs_foo<T: Foo>() {}
    |                 ^^^ required by this bound in `needs_foo`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
index 6bca2b724d2..a6fa7ac7949 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr
index d8605806395..d940c3fd477 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `(): Root` is not satisfied
-  --> $DIR/stacked.rs:17:18
+  --> $DIR/stacked.rs:18:18
    |
 LL |     needs_root::<()>();
    |                  ^^ the trait `Root` is not implemented for `()`
    |
 note: required by a bound in `needs_root`
-  --> $DIR/stacked.rs:14:18
+  --> $DIR/stacked.rs:15:18
    |
 LL | fn needs_root<T: Root>() {}
    |                  ^^^^ required by this bound in `needs_root`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
index d8605806395..d940c3fd477 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `(): Root` is not satisfied
-  --> $DIR/stacked.rs:17:18
+  --> $DIR/stacked.rs:18:18
    |
 LL |     needs_root::<()>();
    |                  ^^ the trait `Root` is not implemented for `()`
    |
 note: required by a bound in `needs_root`
-  --> $DIR/stacked.rs:14:18
+  --> $DIR/stacked.rs:15:18
    |
 LL | fn needs_root<T: Root>() {}
    |                  ^^^^ required by this bound in `needs_root`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
index 842e04b9d90..fd7be35ff84 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 trait Root {}
 trait DontRecommend {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
index 95ccbb92a89..0b07b073172 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/supress_suggestions_in_help.rs:21:11
+  --> $DIR/supress_suggestions_in_help.rs:22:11
    |
 LL |     check(());
    |     ----- ^^ the trait `Foo` is not implemented for `()`
@@ -8,7 +8,7 @@ LL |     check(());
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `check`
-  --> $DIR/supress_suggestions_in_help.rs:18:18
+  --> $DIR/supress_suggestions_in_help.rs:19:18
    |
 LL | fn check(a: impl Foo) {}
    |                  ^^^ required by this bound in `check`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
index 95ccbb92a89..0b07b073172 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/supress_suggestions_in_help.rs:21:11
+  --> $DIR/supress_suggestions_in_help.rs:22:11
    |
 LL |     check(());
    |     ----- ^^ the trait `Foo` is not implemented for `()`
@@ -8,7 +8,7 @@ LL |     check(());
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `check`
-  --> $DIR/supress_suggestions_in_help.rs:18:18
+  --> $DIR/supress_suggestions_in_help.rs:19:18
    |
 LL | fn check(a: impl Foo) {}
    |                  ^^^ required by this bound in `check`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs
index 2c7c1516123..04cf8243a67 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr
index b53febbb71a..31a1ae991ec 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: Very important message!
-  --> $DIR/type_mismatch.rs:23:14
+  --> $DIR/type_mismatch.rs:24:14
    |
 LL |     verify::<u8>();
    |              ^^ the trait `TheImportantOne` is not implemented for `u8`
    |
 note: required by a bound in `verify`
-  --> $DIR/type_mismatch.rs:20:14
+  --> $DIR/type_mismatch.rs:21:14
    |
 LL | fn verify<T: TheImportantOne>() {}
    |              ^^^^^^^^^^^^^^^ required by this bound in `verify`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr
index b53febbb71a..31a1ae991ec 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: Very important message!
-  --> $DIR/type_mismatch.rs:23:14
+  --> $DIR/type_mismatch.rs:24:14
    |
 LL |     verify::<u8>();
    |              ^^ the trait `TheImportantOne` is not implemented for `u8`
    |
 note: required by a bound in `verify`
-  --> $DIR/type_mismatch.rs:20:14
+  --> $DIR/type_mismatch.rs:21:14
    |
 LL | fn verify<T: TheImportantOne>() {}
    |              ^^^^^^^^^^^^^^^ required by this bound in `verify`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs
index 7f30fdb06c7..b5bd14745cd 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 #[diagnostic::on_unimplemented(message = "Very important message!")]
 trait TheImportantOne {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr
index a8429ff60f8..7e348842e19 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/with_lifetime.rs:17:5
+  --> $DIR/with_lifetime.rs:18:5
    |
 LL | fn foo<'a>(a: &'a ()) {
    |        -- lifetime `'a` defined here
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr
index a8429ff60f8..7e348842e19 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/with_lifetime.rs:17:5
+  --> $DIR/with_lifetime.rs:18:5
    |
 LL | fn foo<'a>(a: &'a ()) {
    |        -- lifetime `'a` defined here
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs
index 6a67d83d5fe..98916ed061f 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs
@@ -1,6 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
+//@ reference: attributes.diagnostic.do_not_recommend.intro
 
 trait Root {}
 trait DontRecommend {}
diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.rs b/tests/ui/dropck/dropck-only-error-ambiguity.rs
new file mode 100644
index 00000000000..ddba2af7070
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-ambiguity.rs
@@ -0,0 +1,23 @@
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// Version where the normalization error is an ambiguous trait implementation.
+// <[T] as ToOwned>::Owned is ambiguous on whether to use T: Clone or [T]::Clone.
+// Regression test for #105299
+
+pub trait Foo: Clone {}
+
+pub struct Bar<'a, T: Clone> {
+    pub cow: std::borrow::Cow<'a, [T]>,
+
+    pub THIS_CAUSES_ICE: (),
+}
+
+impl<T> Bar<'_, T>
+where
+    T: Clone,
+    [T]: Foo,
+{
+    pub fn MOVES_SELF(self) {}
+    //~^ ERROR type annotations needed
+}
+
+pub fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.stderr b/tests/ui/dropck/dropck-only-error-ambiguity.stderr
new file mode 100644
index 00000000000..de19bd49f4e
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-ambiguity.stderr
@@ -0,0 +1,11 @@
+error[E0284]: type annotations needed
+  --> $DIR/dropck-only-error-ambiguity.rs:19:23
+   |
+LL |     pub fn MOVES_SELF(self) {}
+   |                       ^^^^ cannot infer type
+   |
+   = note: cannot satisfy `<[T] as ToOwned>::Owned == _`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/crashes/135039.rs b/tests/ui/dropck/dropck-only-error-async.rs
index c4c5336fd4f..71158e3c6ef 100644
--- a/tests/crashes/135039.rs
+++ b/tests/ui/dropck/dropck-only-error-async.rs
@@ -1,7 +1,6 @@
-//@ known-bug: #135039
-//@ edition:2021
-
-pub type UserId<Backend> = <<Backend as AuthnBackend>::User as AuthUser>::Id;
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// issue #135039
+//@ edition:2018
 
 pub trait AuthUser {
     type Id;
@@ -13,7 +12,7 @@ pub trait AuthnBackend {
 
 pub struct AuthSession<Backend: AuthnBackend> {
     user: Option<Backend::User>,
-    data: Option<UserId<Backend>>,
+    data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
 }
 
 pub trait Authz: Sized {
@@ -27,8 +26,12 @@ pub trait Query<User: Authz> {
 
 pub async fn run_query<User: Authz, Q: Query<User> + 'static>(
     auth: AuthSession<User::AuthnBackend>,
+    //~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
+    //~| ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
     query: Q,
 ) -> Result<Q::Output, ()> {
     let user = auth.user;
     query.run().await
 }
+
+fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error-async.stderr b/tests/ui/dropck/dropck-only-error-async.stderr
new file mode 100644
index 00000000000..4a069c8ac33
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-async.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error-async.rs:28:5
+   |
+LL |     auth: AuthSession<User::AuthnBackend>,
+   |     ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error-async.rs:28:5
+   |
+LL |     auth: AuthSession<User::AuthnBackend>,
+   |     ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/crashes/91985.rs b/tests/ui/dropck/dropck-only-error-gat.rs
index 338550430e1..dadcf76a43f 100644
--- a/tests/crashes/91985.rs
+++ b/tests/ui/dropck/dropck-only-error-gat.rs
@@ -1,6 +1,6 @@
-//@ known-bug: #91985
-
-#![feature(generic_associated_types)]
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// Version that uses a generic associated type
+// Regression test for #91985
 
 pub trait Trait1 {
     type Associated: Ord;
@@ -22,7 +22,7 @@ impl GatTrait for GatStruct {
 
 pub struct OuterStruct<T1: Trait1, T2: Trait2> {
     inner: InnerStruct<T2, GatStruct>,
-    t1:    T1,
+    t1: T1,
 }
 
 pub struct InnerStruct<T: Trait2, G: GatTrait> {
@@ -35,6 +35,7 @@ where
     T2: Trait2<Associated = T1::Associated>,
 {
     pub fn new() -> Self {
+        //~^ ERROR the trait bound `<T1 as Trait1>::Associated: Clone` is not satisfied
         todo!()
     }
 }
diff --git a/tests/ui/dropck/dropck-only-error-gat.stderr b/tests/ui/dropck/dropck-only-error-gat.stderr
new file mode 100644
index 00000000000..53982c0826a
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-gat.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `<T1 as Trait1>::Associated: Clone` is not satisfied
+  --> $DIR/dropck-only-error-gat.rs:37:21
+   |
+LL |     pub fn new() -> Self {
+   |                     ^^^^ the trait `Clone` is not implemented for `<T1 as Trait1>::Associated`
+   |
+note: required by a bound in `GatTrait::Gat`
+  --> $DIR/dropck-only-error-gat.rs:14:17
+   |
+LL |     type Gat<T: Clone>;
+   |                 ^^^^^ required by this bound in `GatTrait::Gat`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/dropck-only-error.rs b/tests/ui/dropck/dropck-only-error.rs
new file mode 100644
index 00000000000..e85eeb82e00
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error.rs
@@ -0,0 +1,23 @@
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// issue #135039
+
+pub trait AuthUser {
+    type Id;
+}
+
+pub trait AuthnBackend {
+    type User: AuthUser;
+}
+
+pub struct AuthSession<Backend: AuthnBackend> {
+    data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
+}
+
+pub trait Authz: Sized {
+    type AuthnBackend: AuthnBackend<User = Self>;
+}
+
+pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
+//~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
+
+fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error.stderr b/tests/ui/dropck/dropck-only-error.stderr
new file mode 100644
index 00000000000..6c7cd5d296c
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error.rs:20:31
+   |
+LL | pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
+   |                               ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
index 5386628a8e0..ce3d3fc645d 100644
--- a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
@@ -1,5 +1,5 @@
 //@ needs-llvm-components: avr
-//@ compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+//@ compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib
 #![no_core]
 #![feature(no_core, lang_items)]
 #[lang="sized"]
diff --git a/tests/ui/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.current.stderr
index ac636ebb648..0741cf9581d 100644
--- a/tests/ui/generic-associated-types/issue-91883.stderr
+++ b/tests/ui/generic-associated-types/issue-91883.current.stderr
@@ -1,5 +1,5 @@
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/issue-91883.rs:30:24
+  --> $DIR/issue-91883.rs:34:24
    |
 LL |     type Cursor<'tx>: Cursor<'tx>
    |     ----------------------------- definition of `Cursor` from trait
@@ -8,12 +8,12 @@ LL |     type Cursor<'tx> = CursorImpl<'tx>;
    |                        ^^^^^^^^^^^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'db` as defined here
-  --> $DIR/issue-91883.rs:29:6
+  --> $DIR/issue-91883.rs:33:6
    |
 LL | impl<'db> Transaction<'db> for TransactionImpl<'db> {
    |      ^^^
 note: but lifetime parameter must outlive the lifetime `'tx` as defined here
-  --> $DIR/issue-91883.rs:30:17
+  --> $DIR/issue-91883.rs:34:17
    |
 LL |     type Cursor<'tx> = CursorImpl<'tx>;
    |                 ^^^
diff --git a/tests/ui/generic-associated-types/issue-91883.next.stderr b/tests/ui/generic-associated-types/issue-91883.next.stderr
new file mode 100644
index 00000000000..b3ed2d81b63
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-91883.next.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-91883.rs:34:24
+   |
+LL |     type Cursor<'tx> = CursorImpl<'tx>;
+   |                        ^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'db` as defined here
+  --> $DIR/issue-91883.rs:33:6
+   |
+LL | impl<'db> Transaction<'db> for TransactionImpl<'db> {
+   |      ^^^
+note: but lifetime parameter must outlive the lifetime `'tx` as defined here
+  --> $DIR/issue-91883.rs:34:17
+   |
+LL |     type Cursor<'tx> = CursorImpl<'tx>;
+   |                 ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/tests/ui/generic-associated-types/issue-91883.rs b/tests/ui/generic-associated-types/issue-91883.rs
index e870e08a3a2..d31e1736cf2 100644
--- a/tests/ui/generic-associated-types/issue-91883.rs
+++ b/tests/ui/generic-associated-types/issue-91883.rs
@@ -1,3 +1,7 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 use std::fmt::Debug;
 use std::marker::PhantomData;
 
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index c1a78bc2388..1bbff839ffa 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,5 +1,8 @@
 //@ edition:2021
 //@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 use std::fmt::Debug;
 
diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
index 10c2a811243..6954a7d8067 100644
--- a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 use std::ops::Deref;
 
diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs
index e36be26d003..6548c03d1b0 100644
--- a/tests/ui/implied-bounds/bevy_world_query.rs
+++ b/tests/ui/implied-bounds/bevy_world_query.rs
@@ -1,3 +1,5 @@
+#![crate_name = "bevy_ecs"]
+
 //@ check-pass
 
 // We currently special case bevy from erroring on incorrect implied bounds
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
index f498257e12f..f8ee6fef824 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements
   --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5
    |
 LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str {
@@ -25,4 +25,4 @@ LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr
index fe310998f09..bed75ed6ba2 100644
--- a/tests/ui/issues/issue-20831-debruijn.stderr
+++ b/tests/ui/issues/issue-20831-debruijn.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/issue-20831-debruijn.rs:28:33
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
@@ -48,4 +48,4 @@ LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs
index 81dc7285254..b87a1d2031d 100644
--- a/tests/ui/layout/debug.rs
+++ b/tests/ui/layout/debug.rs
@@ -82,3 +82,8 @@ type Impossible = (str, str); //~ ERROR: cannot be known at compilation time
 #[rustc_layout(debug)]
 union EmptyUnion {} //~ ERROR: has an unknown layout
 //~^ ERROR: unions cannot have zero fields
+
+// Test the error message of `LayoutError::TooGeneric`
+// (this error is never emitted to users).
+#[rustc_layout(debug)]
+type TooGeneric<T> = T; //~ ERROR: does not have a fixed layout
diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr
index 319c0de26a9..07cad776692 100644
--- a/tests/ui/layout/debug.stderr
+++ b/tests/ui/layout/debug.stderr
@@ -31,6 +31,7 @@ error: layout_of(E) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -56,6 +57,7 @@ error: layout_of(E) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -69,7 +71,9 @@ error: layout_of(E) = Layout {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -83,6 +87,7 @@ error: layout_of(E) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 1,
                        },
@@ -136,6 +141,7 @@ error: layout_of(S) = Layout {
                ],
            },
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -161,6 +167,7 @@ error: layout_of(U) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -213,6 +220,7 @@ error: layout_of(Result<i32, i32>) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -255,6 +263,7 @@ error: layout_of(Result<i32, i32>) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -293,6 +302,7 @@ error: layout_of(Result<i32, i32>) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -328,6 +338,7 @@ error: layout_of(i32) = Layout {
            ),
            fields: Primitive,
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -353,6 +364,7 @@ error: layout_of(V) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -378,6 +390,7 @@ error: layout_of(W) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -403,6 +416,7 @@ error: layout_of(Y) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -428,6 +442,7 @@ error: layout_of(P1) = Layout {
                1,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -453,6 +468,7 @@ error: layout_of(P2) = Layout {
                1,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -478,6 +494,7 @@ error: layout_of(P3) = Layout {
                1,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -503,6 +520,7 @@ error: layout_of(P4) = Layout {
                1,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -533,6 +551,7 @@ error: layout_of(P5) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -563,6 +582,7 @@ error: layout_of(MaybeUninit<u8>) = Layout {
                2,
            ),
            largest_niche: None,
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -596,12 +616,18 @@ error: the type has an unknown layout
 LL | union EmptyUnion {}
    | ^^^^^^^^^^^^^^^^
 
+error: the type `T` does not have a fixed layout
+  --> $DIR/debug.rs:89:1
+   |
+LL | type TooGeneric<T> = T;
+   | ^^^^^^^^^^^^^^^^^^
+
 error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
   --> $DIR/debug.rs:75:5
    |
 LL |     const C: () = ();
    |     ^^^^^^^^^^^
 
-error: aborting due to 19 previous errors
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr
index 96f0a8c8740..90c06ba1f83 100644
--- a/tests/ui/layout/hexagon-enum.stderr
+++ b/tests/ui/layout/hexagon-enum.stderr
@@ -31,6 +31,7 @@ error: layout_of(A) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -56,6 +57,7 @@ error: layout_of(A) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +109,7 @@ error: layout_of(B) = Layout {
                    valid_range: 255..=255,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -132,6 +135,7 @@ error: layout_of(B) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -183,6 +187,7 @@ error: layout_of(C) = Layout {
                    valid_range: 256..=256,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -208,6 +213,7 @@ error: layout_of(C) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -259,6 +265,7 @@ error: layout_of(P) = Layout {
                    valid_range: 268435456..=268435456,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -284,6 +291,7 @@ error: layout_of(P) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -335,6 +343,7 @@ error: layout_of(T) = Layout {
                    valid_range: 2164260864..=2164260864,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -360,6 +369,7 @@ error: layout_of(T) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index cd9e4c02781..3bdb9c5c143 100644
--- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -37,6 +37,7 @@ error: layout_of(MissingPayloadField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -78,6 +79,7 @@ error: layout_of(MissingPayloadField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -99,6 +101,7 @@ error: layout_of(MissingPayloadField) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -157,6 +160,7 @@ error: layout_of(CommonPayloadField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -199,6 +203,7 @@ error: layout_of(CommonPayloadField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -237,6 +242,7 @@ error: layout_of(CommonPayloadField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -294,6 +300,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -335,6 +342,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -372,6 +380,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -429,6 +438,7 @@ error: layout_of(NicheFirst) = Layout {
                    valid_range: 0..=4,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -486,6 +496,7 @@ error: layout_of(NicheFirst) = Layout {
                                valid_range: 0..=2,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -507,6 +518,7 @@ error: layout_of(NicheFirst) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -528,6 +540,7 @@ error: layout_of(NicheFirst) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 2,
                        },
@@ -585,6 +598,7 @@ error: layout_of(NicheSecond) = Layout {
                    valid_range: 0..=4,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -642,6 +656,7 @@ error: layout_of(NicheSecond) = Layout {
                                valid_range: 0..=2,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -663,6 +678,7 @@ error: layout_of(NicheSecond) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -684,6 +700,7 @@ error: layout_of(NicheSecond) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 2,
                        },
diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr
index 15a3f6004f5..1d4e4436448 100644
--- a/tests/ui/layout/issue-96185-overaligned-enum.stderr
+++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr
@@ -25,6 +25,7 @@ error: layout_of(Aligned1) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -50,6 +51,7 @@ error: layout_of(Aligned1) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -73,6 +75,7 @@ error: layout_of(Aligned1) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -128,6 +131,7 @@ error: layout_of(Aligned2) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -153,6 +157,7 @@ error: layout_of(Aligned2) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -176,6 +181,7 @@ error: layout_of(Aligned2) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/layout/normalization-failure.rs b/tests/ui/layout/normalization-failure.rs
new file mode 100644
index 00000000000..c0f8710c03c
--- /dev/null
+++ b/tests/ui/layout/normalization-failure.rs
@@ -0,0 +1,57 @@
+//! This test demonstrates how `LayoutError::NormalizationFailure` can happen and why
+//! it is necessary.
+//!
+//! This code does not cause an immediate normalization error in typeck, because we
+//! don't reveal the hidden type returned by `opaque<T>` in the analysis typing mode.
+//! Instead, `<{opaque} as Project2>::Assoc2` is a *rigid projection*, because we know
+//! that `{opaque}: Project2` holds, due to the opaque type's `impl Project2` bound,
+//! but cannot normalize `<{opaque} as Project2>::Assoc2` any further.
+//!
+//! However, in the post-analysis typing mode, which is used for the layout computation,
+//! the opaque's hidden type is revealed to be `PhantomData<T>`, and now we fail to
+//! normalize `<PhantomData<T> as Project2>::Assoc2` if there is a `T: Project1` bound
+//! in the param env! This happens, because `PhantomData<T>: Project2` only holds if
+//! `<T as Project1>::Assoc1 == ()` holds. This would usually be satisfied by the
+//! blanket `impl<T> Project1 for T`, but due to the `T: Project1` bound we do not
+//! normalize `<T as Project1>::Assoc1` via the impl and treat it as rigid instead.
+//! Therefore, `PhantomData<T>: Project2` does NOT hold and normalizing
+//! `<PhantomData<T> as Project2>::Assoc2` fails.
+//!
+//! Note that this layout error can only happen when computing the layout in a generic
+//! context, which is not required for codegen, but may happen for lints, MIR optimizations,
+//! and the transmute check.
+
+use std::marker::PhantomData;
+
+trait Project1 {
+    type Assoc1;
+}
+
+impl<T> Project1 for T {
+    type Assoc1 = ();
+}
+
+trait Project2 {
+    type Assoc2;
+    fn get(self) -> Self::Assoc2;
+}
+
+impl<T: Project1<Assoc1 = ()>> Project2 for PhantomData<T> {
+    type Assoc2 = ();
+    fn get(self) -> Self::Assoc2 {}
+}
+
+fn opaque<T>() -> impl Project2 {
+    PhantomData::<T>
+}
+
+fn check<T: Project1>() {
+    unsafe {
+        std::mem::transmute::<_, ()>(opaque::<T>().get());
+        //~^ ERROR: cannot transmute
+        //~| NOTE: (unable to determine layout for `<impl Project2 as Project2>::Assoc2` because `<impl Project2 as Project2>::Assoc2` cannot be normalized)
+        //~| NOTE: (0 bits)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/layout/normalization-failure.stderr b/tests/ui/layout/normalization-failure.stderr
new file mode 100644
index 00000000000..5fe38d4403a
--- /dev/null
+++ b/tests/ui/layout/normalization-failure.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/normalization-failure.rs:50:9
+   |
+LL |         std::mem::transmute::<_, ()>(opaque::<T>().get());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `<impl Project2 as Project2>::Assoc2` (unable to determine layout for `<impl Project2 as Project2>::Assoc2` because `<impl Project2 as Project2>::Assoc2` cannot be normalized)
+   = note: target type: `()` (0 bits)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr
index 120081d193c..0c343318564 100644
--- a/tests/ui/layout/thumb-enum.stderr
+++ b/tests/ui/layout/thumb-enum.stderr
@@ -31,6 +31,7 @@ error: layout_of(A) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -56,6 +57,7 @@ error: layout_of(A) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +109,7 @@ error: layout_of(B) = Layout {
                    valid_range: 255..=255,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -132,6 +135,7 @@ error: layout_of(B) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -183,6 +187,7 @@ error: layout_of(C) = Layout {
                    valid_range: 256..=256,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -208,6 +213,7 @@ error: layout_of(C) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -259,6 +265,7 @@ error: layout_of(P) = Layout {
                    valid_range: 268435456..=268435456,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -284,6 +291,7 @@ error: layout_of(P) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -335,6 +343,7 @@ error: layout_of(T) = Layout {
                    valid_range: 2164260864..=2164260864,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -360,6 +369,7 @@ error: layout_of(T) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr
index b6fcc14c063..33d2eede220 100644
--- a/tests/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr
@@ -25,6 +25,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -54,6 +55,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -88,6 +90,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                                valid_range: 0..=1,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -133,6 +136,7 @@ error: layout_of(MultipleAlignments) = Layout {
                    valid_range: 0..=2,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -162,6 +166,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -187,6 +192,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -221,6 +227,7 @@ error: layout_of(MultipleAlignments) = Layout {
                                valid_range: 0..=1,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 2,
                        },
@@ -266,6 +273,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -295,6 +303,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -329,6 +338,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                                valid_range: 1..=65535,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -374,6 +384,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -407,6 +418,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -441,6 +453,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                                valid_range: 0..=0,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
index 8f8000fe34d..87a906761c0 100644
--- a/tests/ui/lint/invalid_from_utf8.rs
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(concat_bytes)]
-#![feature(inherent_str_constructors)]
 #![warn(invalid_from_utf8_unchecked)]
 #![warn(invalid_from_utf8)]
 
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
index 715ecf56f21..3cd4d227fc2 100644
--- a/tests/ui/lint/invalid_from_utf8.stderr
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:22:9
+  --> $DIR/invalid_from_utf8.rs:21:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -7,13 +7,13 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112
    |                                                the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:5:9
+  --> $DIR/invalid_from_utf8.rs:4:9
    |
 LL | #![warn(invalid_from_utf8_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:24:9
+  --> $DIR/invalid_from_utf8.rs:23:9
    |
 LL |         str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -21,7 +21,7 @@ LL |         str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121
    |                                           the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:26:9
+  --> $DIR/invalid_from_utf8.rs:25:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -29,7 +29,7 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i',
    |                                                the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:28:9
+  --> $DIR/invalid_from_utf8.rs:27:9
    |
 LL |         str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -37,7 +37,7 @@ LL |         str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p',
    |                                           the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:50:9
+  --> $DIR/invalid_from_utf8.rs:49:9
    |
 LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -45,7 +45,7 @@ LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:52:9
+  --> $DIR/invalid_from_utf8.rs:51:9
    |
 LL |         str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -53,7 +53,7 @@ LL |         str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |                                   the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:54:9
+  --> $DIR/invalid_from_utf8.rs:53:9
    |
 LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -61,7 +61,7 @@ LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:56:9
+  --> $DIR/invalid_from_utf8.rs:55:9
    |
 LL |         str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -69,7 +69,7 @@ LL |         str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b
    |                                   the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:58:9
+  --> $DIR/invalid_from_utf8.rs:57:9
    |
 LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
@@ -77,7 +77,7 @@ LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:60:9
+  --> $DIR/invalid_from_utf8.rs:59:9
    |
 LL |         str::from_utf8_unchecked(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
@@ -85,7 +85,7 @@ LL |         str::from_utf8_unchecked(b"cl\x82ippy");
    |                                  the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:62:9
+  --> $DIR/invalid_from_utf8.rs:61:9
    |
 LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -93,7 +93,7 @@ LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:64:9
+  --> $DIR/invalid_from_utf8.rs:63:9
    |
 LL |         str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -101,7 +101,7 @@ LL |         str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |                                  the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:84:9
+  --> $DIR/invalid_from_utf8.rs:83:9
    |
 LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -109,13 +109,13 @@ LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |                                      the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:6:9
+  --> $DIR/invalid_from_utf8.rs:5:9
    |
 LL | #![warn(invalid_from_utf8)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:86:9
+  --> $DIR/invalid_from_utf8.rs:85:9
    |
 LL |         str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -123,7 +123,7 @@ LL |         str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |                                 the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:88:9
+  --> $DIR/invalid_from_utf8.rs:87:9
    |
 LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -131,7 +131,7 @@ LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p'
    |                                      the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:90:9
+  --> $DIR/invalid_from_utf8.rs:89:9
    |
 LL |         str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -139,7 +139,7 @@ LL |         str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y
    |                                 the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:112:9
+  --> $DIR/invalid_from_utf8.rs:111:9
    |
 LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -147,7 +147,7 @@ LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:114:9
+  --> $DIR/invalid_from_utf8.rs:113:9
    |
 LL |         str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^----------------------------------^
@@ -155,7 +155,7 @@ LL |         str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |                         the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:116:9
+  --> $DIR/invalid_from_utf8.rs:115:9
    |
 LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -163,7 +163,7 @@ LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y'])
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:118:9
+  --> $DIR/invalid_from_utf8.rs:117:9
    |
 LL |         str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -171,7 +171,7 @@ LL |         str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |                         the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:120:9
+  --> $DIR/invalid_from_utf8.rs:119:9
    |
 LL |         std::str::from_utf8(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^-------------^
@@ -179,7 +179,7 @@ LL |         std::str::from_utf8(b"cl\x82ippy");
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:122:9
+  --> $DIR/invalid_from_utf8.rs:121:9
    |
 LL |         str::from_utf8(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^-------------^
@@ -187,7 +187,7 @@ LL |         str::from_utf8(b"cl\x82ippy");
    |                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:124:9
+  --> $DIR/invalid_from_utf8.rs:123:9
    |
 LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -195,7 +195,7 @@ LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:126:9
+  --> $DIR/invalid_from_utf8.rs:125:9
    |
 LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^---------------------------------^
@@ -203,7 +203,7 @@ LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:133:5
+  --> $DIR/invalid_from_utf8.rs:132:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -211,7 +211,7 @@ LL |     std::str::from_utf8_mut(&mut a);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:135:5
+  --> $DIR/invalid_from_utf8.rs:134:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -220,7 +220,7 @@ LL |     str::from_utf8_mut(&mut a);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:139:5
+  --> $DIR/invalid_from_utf8.rs:138:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -229,7 +229,7 @@ LL |     std::str::from_utf8_mut(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:141:5
+  --> $DIR/invalid_from_utf8.rs:140:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -238,7 +238,7 @@ LL |     str::from_utf8_mut(c);
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:144:5
+  --> $DIR/invalid_from_utf8.rs:143:5
    |
 LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
    |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -246,7 +246,7 @@ LL |     std::str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:146:5
+  --> $DIR/invalid_from_utf8.rs:145:5
    |
 LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
    |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -255,7 +255,7 @@ LL |     str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:149:5
+  --> $DIR/invalid_from_utf8.rs:148:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -263,7 +263,7 @@ LL |     std::str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:151:5
+  --> $DIR/invalid_from_utf8.rs:150:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -272,7 +272,7 @@ LL |     str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:154:5
+  --> $DIR/invalid_from_utf8.rs:153:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -280,7 +280,7 @@ LL |     std::str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:156:5
+  --> $DIR/invalid_from_utf8.rs:155:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -289,7 +289,7 @@ LL |     str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:159:5
+  --> $DIR/invalid_from_utf8.rs:158:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -297,7 +297,7 @@ LL |     std::str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:161:5
+  --> $DIR/invalid_from_utf8.rs:160:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -306,7 +306,7 @@ LL |     str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:164:5
+  --> $DIR/invalid_from_utf8.rs:163:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -314,7 +314,7 @@ LL |     std::str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:166:5
+  --> $DIR/invalid_from_utf8.rs:165:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs
index 51f868706b6..860fc5046d1 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.rs
+++ b/tests/ui/lint/unused/unused_attributes-must_use.rs
@@ -79,6 +79,11 @@ trait Use {
 #[must_use] //~ ERROR `#[must_use]` has no effect
 impl Use for () {
     type AssocTy = ();
+
+    #[must_use] //~ ERROR `#[must_use]` has no effect
+    fn get_four(&self) -> usize {
+        4
+    }
 }
 
 #[must_use] //~ ERROR `#[must_use]` has no effect
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 9633767c442..28fd8eeb8cb 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -76,43 +76,43 @@ LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a trait alias
-  --> $DIR/unused_attributes-must_use.rs:84:1
+  --> $DIR/unused_attributes-must_use.rs:89:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a macro def
-  --> $DIR/unused_attributes-must_use.rs:87:1
+  --> $DIR/unused_attributes-must_use.rs:92:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a statement
-  --> $DIR/unused_attributes-must_use.rs:95:5
+  --> $DIR/unused_attributes-must_use.rs:100:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a closure
-  --> $DIR/unused_attributes-must_use.rs:99:13
+  --> $DIR/unused_attributes-must_use.rs:104:13
    |
 LL |     let x = #[must_use]
    |             ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to an match arm
-  --> $DIR/unused_attributes-must_use.rs:121:9
+  --> $DIR/unused_attributes-must_use.rs:126:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a struct field
-  --> $DIR/unused_attributes-must_use.rs:129:28
+  --> $DIR/unused_attributes-must_use.rs:134:28
    |
 LL |     let s = PatternField { #[must_use]  foo: 123 };
    |                            ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a pattern field
-  --> $DIR/unused_attributes-must_use.rs:130:24
+  --> $DIR/unused_attributes-must_use.rs:135:24
    |
 LL |     let PatternField { #[must_use] foo } = s;
    |                        ^^^^^^^^^^^
@@ -129,6 +129,12 @@ error: `#[must_use]` has no effect when applied to an associated type
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
+error: `#[must_use]` has no effect when applied to a provided trait method
+  --> $DIR/unused_attributes-must_use.rs:83:5
+   |
+LL |     #[must_use]
+   |     ^^^^^^^^^^^
+
 error: `#[must_use]` has no effect when applied to a foreign static item
   --> $DIR/unused_attributes-must_use.rs:50:5
    |
@@ -136,7 +142,7 @@ LL |     #[must_use]
    |     ^^^^^^^^^^^
 
 error: unused `X` that must be used
-  --> $DIR/unused_attributes-must_use.rs:103:5
+  --> $DIR/unused_attributes-must_use.rs:108:5
    |
 LL |     X;
    |     ^
@@ -152,7 +158,7 @@ LL |     let _ = X;
    |     +++++++
 
 error: unused `Y` that must be used
-  --> $DIR/unused_attributes-must_use.rs:104:5
+  --> $DIR/unused_attributes-must_use.rs:109:5
    |
 LL |     Y::Z;
    |     ^^^^
@@ -163,7 +169,7 @@ LL |     let _ = Y::Z;
    |     +++++++
 
 error: unused `U` that must be used
-  --> $DIR/unused_attributes-must_use.rs:105:5
+  --> $DIR/unused_attributes-must_use.rs:110:5
    |
 LL |     U { unit: () };
    |     ^^^^^^^^^^^^^^
@@ -174,7 +180,7 @@ LL |     let _ = U { unit: () };
    |     +++++++
 
 error: unused return value of `U::method` that must be used
-  --> $DIR/unused_attributes-must_use.rs:106:5
+  --> $DIR/unused_attributes-must_use.rs:111:5
    |
 LL |     U::method();
    |     ^^^^^^^^^^^
@@ -185,7 +191,7 @@ LL |     let _ = U::method();
    |     +++++++
 
 error: unused return value of `foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:107:5
+  --> $DIR/unused_attributes-must_use.rs:112:5
    |
 LL |     foo();
    |     ^^^^^
@@ -196,7 +202,7 @@ LL |     let _ = foo();
    |     +++++++
 
 error: unused return value of `foreign_foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:110:9
+  --> $DIR/unused_attributes-must_use.rs:115:9
    |
 LL |         foreign_foo();
    |         ^^^^^^^^^^^^^
@@ -207,7 +213,7 @@ LL |         let _ = foreign_foo();
    |         +++++++
 
 error: unused return value of `Use::get_four` that must be used
-  --> $DIR/unused_attributes-must_use.rs:118:5
+  --> $DIR/unused_attributes-must_use.rs:123:5
    |
 LL |     ().get_four();
    |     ^^^^^^^^^^^^^
@@ -217,5 +223,5 @@ help: use `let _ = ...` to ignore the resulting value
 LL |     let _ = ().get_four();
    |     +++++++
 
-error: aborting due to 28 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/nll/normalization-bounds-error.stderr b/tests/ui/nll/normalization-bounds-error.stderr
index d4254881863..47d2663313d 100644
--- a/tests/ui/nll/normalization-bounds-error.stderr
+++ b/tests/ui/nll/normalization-bounds-error.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
   --> $DIR/normalization-bounds-error.rs:12:31
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
@@ -36,4 +36,4 @@ LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/parser/doc-before-bad-variant.rs b/tests/ui/parser/doc-before-bad-variant.rs
new file mode 100644
index 00000000000..bfede28c108
--- /dev/null
+++ b/tests/ui/parser/doc-before-bad-variant.rs
@@ -0,0 +1,6 @@
+enum TestEnum {
+    Works,
+    /// Some documentation
+    Self, //~ ERROR expected identifier, found keyword `Self`
+    //~^ HELP enum variants can be
+}
diff --git a/tests/ui/parser/doc-before-bad-variant.stderr b/tests/ui/parser/doc-before-bad-variant.stderr
new file mode 100644
index 00000000000..5e4d4116f25
--- /dev/null
+++ b/tests/ui/parser/doc-before-bad-variant.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/doc-before-bad-variant.rs:4:5
+   |
+LL | enum TestEnum {
+   |      -------- while parsing this enum
+...
+LL |     Self,
+   |     ^^^^ expected identifier, found keyword
+   |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/doc-before-syntax-error.rs b/tests/ui/parser/doc-before-syntax-error.rs
new file mode 100644
index 00000000000..435f497d186
--- /dev/null
+++ b/tests/ui/parser/doc-before-syntax-error.rs
@@ -0,0 +1,2 @@
+/// Some documentation
+<> //~ ERROR expected identifier
diff --git a/tests/ui/parser/doc-before-syntax-error.stderr b/tests/ui/parser/doc-before-syntax-error.stderr
new file mode 100644
index 00000000000..93e39d63000
--- /dev/null
+++ b/tests/ui/parser/doc-before-syntax-error.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `<`
+  --> $DIR/doc-before-syntax-error.rs:2:1
+   |
+LL | <>
+   | ^ expected identifier
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs
index daa9b7368fd..b18f87fd569 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs
@@ -9,3 +9,10 @@ macro_rules! mixed_edition_pat {
         Some(mut $foo)
     };
 }
+
+#[macro_export]
+macro_rules! bind_ref {
+    ($foo:ident) => {
+        ref $foo
+    };
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs
new file mode 100644
index 00000000000..14d26be91a0
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs
@@ -0,0 +1,48 @@
+//@[classic2021] edition: 2024
+//@[structural2021] edition: 2024
+//@[classic2024] edition: 2021
+//@[structural2024] edition: 2021
+//! This contains macros in an edition *different* to the one used in `../mixed-editions.rs`, in
+//! order to test typing mixed-edition patterns.
+
+#[macro_export]
+macro_rules! match_ctor {
+    ($p:pat) => {
+        [$p]
+    };
+}
+
+#[macro_export]
+macro_rules! match_ref {
+    ($p:pat) => {
+        &$p
+    };
+}
+
+#[macro_export]
+macro_rules! bind {
+    ($i:ident) => {
+        $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_ref {
+    ($i:ident) => {
+        ref $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_mut {
+    ($i:ident) => {
+        mut $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_ref_mut {
+    ($i:ident) => {
+        ref mut $i
+    }
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr
new file mode 100644
index 00000000000..355a8af6760
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr
@@ -0,0 +1,37 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/borrowck-errors.rs:31:29
+   |
+LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+   |                       -     ^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       data moved here
+   |                       move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:36:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:41:23
+   |
+LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
+   |                       ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:46:11
+   |
+LL |     let &[x] = &&mut [0];
+   |           ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
index 1c446178308..d40bdb9111b 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
@@ -1,25 +1,25 @@
-error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:13:16
+error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
+  --> $DIR/borrowck-errors.rs:15:16
    |
 LL |     let [&x] = &[&mut 0];
    |           -    ^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |           move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
 LL |     let [&ref x] = &[&mut 0];
    |           +++
 
-error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:19:16
+error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
+  --> $DIR/borrowck-errors.rs:22:16
    |
 LL |     let [&x] = &mut [&mut 0];
    |           -    ^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |           move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
@@ -27,7 +27,7 @@ LL |     let [&ref x] = &mut [&mut 0];
    |           +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -42,25 +42,25 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:37:23
+  --> $DIR/borrowck-errors.rs:41:23
    |
 LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
    |                       ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:42:11
+  --> $DIR/borrowck-errors.rs:46:11
    |
 LL |     let &[x] = &&mut [0];
    |           ^ cannot borrow as mutable
 
 error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:46:20
+  --> $DIR/borrowck-errors.rs:50:20
    |
 LL |     let [&mut x] = &mut [&mut 0];
    |               -    ^^^^^^^^^^^^^ cannot move out of here
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
index 59cafc50d86..621ca7cc792 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
@@ -1,11 +1,13 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Tests for pattern errors not handled by the pattern typing rules, but by borrowck.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 /// These patterns additionally use `&` to match a `&mut` reference type, which causes compilation
 /// to fail in HIR typeck on stable. As such, they need to be separate from the other tests.
@@ -14,13 +16,15 @@ fn errors_caught_in_hir_typeck_on_stable() {
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
     //[classic2024]~^^^ ERROR: cannot move out of type
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 
     let [&x] = &mut [&mut 0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
     //[classic2024]~^^^ ERROR: cannot move out of type
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 }
 
 pub fn main() {
@@ -35,16 +39,16 @@ pub fn main() {
     // For 2021 edition, this is also a regression test for #136223
     // since the maximum mutability is downgraded during the pattern check process.
     if let &Some(Some(x)) = &Some(&mut Some(0)) {
-        //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
-        let _: &u32 = x;
+        //[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+        #[cfg(any(structural2021, structural2024))] let _: &u32 = x;
     }
 
     let &[x] = &&mut [0];
-    //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
-    let _: &u32 = x;
+    //[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] let _: &u32 = x;
 
     let [&mut x] = &mut [&mut 0];
     //[classic2024]~^ ERROR: cannot move out of type
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(structural2024)] let _: &mut u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
index deefe21ca7d..edcf9f30357 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/borrowck-errors.rs:13:10
+  --> $DIR/borrowck-errors.rs:15:10
    |
 LL |     let [&x] = &[&mut 0];
    |          ^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -15,7 +15,7 @@ LL +     let [x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/borrowck-errors.rs:19:10
+  --> $DIR/borrowck-errors.rs:22:10
    |
 LL |     let [&x] = &mut [&mut 0];
    |          ^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -31,7 +31,7 @@ LL +     let [x] = &mut [&mut 0];
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -46,19 +46,19 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:37:23
+  --> $DIR/borrowck-errors.rs:41:23
    |
 LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
    |                       ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:42:11
+  --> $DIR/borrowck-errors.rs:46:11
    |
 LL |     let &[x] = &&mut [0];
    |           ^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr
new file mode 100644
index 00000000000..208f6c8bbed
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr
@@ -0,0 +1,25 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/borrowck-errors.rs:31:29
+   |
+LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+   |                       -     ^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       data moved here
+   |                       move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:36:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
index 30d2f9f3d70..208f6c8bbed 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr
new file mode 100644
index 00000000000..7e3caaf9797
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr
@@ -0,0 +1,103 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:41:10
+   |
+LL |     let [bind_mut!(y)] = &[0];
+   |          ^^^^^^^^^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: this error originates in the macro `bind_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:76:21
+   |
+LL |     let match_ref!([x]) = &mut &mut [0];
+   |                     ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:80:22
+   |
+LL |     let &match_ctor!(y) = &mut &mut [0];
+   |         -            ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:84:17
+   |
+LL |     let &[bind!(z)] = &mut &mut [0];
+   |         -       ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:30:10
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |          ^^^^^^^^^^^^ occurs within macro expansion
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/mixed-editions.rs:30:9
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |         ^^^^^^^^^^^^^^ this matches on type `&_`
+   = note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: make the implied reference pattern explicit
+   |
+LL |     let &[bind_ref!(y)] = &[0];
+   |         +
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:61:21
+   |
+LL |     let match_ref!([x]) = &&mut [0];
+   |                     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:65:22
+   |
+LL |     let &match_ctor!(y) = &&mut [0];
+   |                      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:69:11
+   |
+LL |     let &[bind!(z)] = &&mut [0];
+   |           ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `bind` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr
new file mode 100644
index 00000000000..466993a1671
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr
@@ -0,0 +1,97 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:37:21
+   |
+LL |     let match_ctor!(mut x) = &[0];
+   |                     ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:76:21
+   |
+LL |     let match_ref!([x]) = &mut &mut [0];
+   |                     ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:80:22
+   |
+LL |     let &match_ctor!(y) = &mut &mut [0];
+   |         -            ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:84:17
+   |
+LL |     let &[bind!(z)] = &mut &mut [0];
+   |         -       ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:26:21
+   |
+LL |     let match_ctor!(ref x) = &[0];
+   |                     ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+help: make the implied reference pattern explicit
+  --> $DIR/auxiliary/mixed-editions-macros.rs:11:9
+   |
+LL |         &[$p]
+   |         +
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:61:21
+   |
+LL |     let match_ref!([x]) = &&mut [0];
+   |                     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:65:22
+   |
+LL |     let &match_ctor!(y) = &&mut [0];
+   |                      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:69:11
+   |
+LL |     let &[bind!(z)] = &&mut [0];
+   |           ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `bind` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs
new file mode 100644
index 00000000000..0a22b55ab63
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs
@@ -0,0 +1,122 @@
+//@ revisions: classic2021 structural2021 classic2024 structural2024
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
+//@[classic2024] edition: 2024
+//@[structural2024] edition: 2024
+//@ aux-build:mixed-editions-macros.rs
+//! Tests for typing mixed-edition patterns under the `ref_pat_eat_one_layer_2024` and
+//! `ref_pat_eat_one_layer_2024_structural` feature gates.
+//! This is meant both to check that patterns are typed with edition-appropriate typing rules and
+//! that we keep our internal state consistent when mixing editions.
+#![allow(incomplete_features, unused)]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
+
+extern crate mixed_editions_macros;
+use mixed_editions_macros::*;
+
+// Tests type equality in a way that avoids coercing `&&T` to `&T`.
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
+
+/// Make sure binding with `ref` in the presence of an inherited reference is forbidden when and
+/// only when the binding is from edition 2024.
+fn ref_binding_tests() {
+    let match_ctor!(ref x) = &[0];
+    //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, &0u32);
+
+    let [bind_ref!(y)] = &[0];
+    //[classic2021,structural2021]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, &0u32);
+}
+
+/// Likewise, when binding with `mut`.
+fn mut_binding_tests() {
+    let match_ctor!(mut x) = &[0];
+    //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, 0u32);
+
+    let [bind_mut!(y)] = &[0];
+    //[classic2021,structural2021]~^ ERROR: binding cannot be both mutable and by-reference
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, 0u32);
+}
+
+/// Make sure reference patterns correspond to one deref on edition 2024 and two on edition 2021.
+fn layers_eaten_tests() {
+    let match_ctor!(&x) = &[&0];
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, 0u32);
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(x, &0u32);
+
+    let [match_ref!(y)] = &[&0];
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(y, &0u32);
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, 0u32);
+}
+
+/// Make sure downgrading mutable binding modes inside shared refs ("Rule 3") doesn't break.
+/// This only applies to `ref_pat_eat_one_layer_2024_structural`, which has Rule 3 in all editions;
+/// under `ref_pat_eat_one_layer_2024`, these should be errors.
+fn rule_3_tests() {
+    let match_ref!([x]) = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(x, &0u32);
+
+    let &match_ctor!(y) = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(y, &0u32);
+
+    let &[bind!(z)] = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(z, &0u32);
+}
+
+/// Test that the interaction between Rules 3 and 5 doesn't break.
+fn rules_3_and_5_tests() {
+    let match_ref!([x]) = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(x, &0u32);
+
+    let &match_ctor!(y) = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(y, &0u32);
+
+    let &[bind!(z)] = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(z, &0u32);
+}
+
+/// Make sure matching a lone shared reference with a `&` ("Rule 4") doesn't break.
+fn rule_4_tests() {
+    let match_ref!([x]) = &[0];
+    assert_type_eq(x, 0u32);
+
+    let &match_ctor!(y) = &[0];
+    assert_type_eq(y, 0u32);
+}
+
+/// Make sure matching a `&mut` reference with a `&` pattern ("Rule 5") doesn't break.
+fn rule_5_tests() {
+    let match_ref!(x) = &mut 0;
+    assert_type_eq(x, 0u32);
+
+    // also test inherited references (assumes rule 4)
+    let [match_ref!(y)] = &mut [0];
+    assert_type_eq(y, 0u32);
+}
+
+/// Make sure binding with `ref mut` is an error within a `&` pattern matching a `&mut` reference.
+fn rule_5_mutability_error_tests() {
+    let match_ref!(ref mut x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let &bind_ref_mut!(x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+
+    // also test inherited references (assumes rule 4)
+    let [match_ref!(ref mut x)] = &mut [0];
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let [&bind_ref_mut!(x)] = &mut [0];
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr
new file mode 100644
index 00000000000..4075dc9529d
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr
@@ -0,0 +1,61 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:41:10
+   |
+LL |     let [bind_mut!(y)] = &[0];
+   |          ^^^^^^^^^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: this error originates in the macro `bind_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:30:10
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |          ^^^^^^^^^^^^ occurs within macro expansion
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/mixed-editions.rs:30:9
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |         ^^^^^^^^^^^^^^ this matches on type `&_`
+   = note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: make the implied reference pattern explicit
+   |
+LL |     let &[bind_ref!(y)] = &[0];
+   |         +
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr
new file mode 100644
index 00000000000..819a54299ea
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr
@@ -0,0 +1,55 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:37:21
+   |
+LL |     let match_ctor!(mut x) = &[0];
+   |                     ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:26:21
+   |
+LL |     let match_ctor!(ref x) = &[0];
+   |                     ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+help: make the implied reference pattern explicit
+  --> $DIR/auxiliary/mixed-editions-macros.rs:11:9
+   |
+LL |         &[$p]
+   |         +
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
index fa95b2b5a57..6ddced3d168 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:14:13
+  --> $DIR/mut-ref-mut.rs:18:13
    |
 LL |     let Foo(mut a) = &Foo(0);
    |             ^^^^
@@ -9,7 +9,7 @@ LL |     let Foo(mut a) = &Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:19:13
+  --> $DIR/mut-ref-mut.rs:23:13
    |
 LL |     let Foo(mut a) = &mut Foo(0);
    |             ^^^^
@@ -19,7 +19,7 @@ LL |     let Foo(mut a) = &mut Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/mut-ref-mut.rs:24:10
+  --> $DIR/mut-ref-mut.rs:28:10
    |
 LL |     let [&mut mut x] = &[&mut 0];
    |          ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
index fbd6514df73..c8e988ad76d 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
@@ -1,29 +1,33 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[stable2021] run-pass
+//@[classic2021] run-pass
+//@[structural2021] run-pass
 //! Test diagnostics for binding with `mut` when the default binding mode is by-ref.
 #![allow(incomplete_features, unused_assignments, unused_variables)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     struct Foo(u8);
 
     let Foo(mut a) = &Foo(0);
     //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { a = 42 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { a = 42 }
     #[cfg(any(classic2024, structural2024))] { a = &42 }
 
     let Foo(mut a) = &mut Foo(0);
     //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { a = 42 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { a = 42 }
     #[cfg(any(classic2024, structural2024))] { a = &mut 42 }
 
     let [&mut mut x] = &[&mut 0];
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
     //[structural2024]~^^^ binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { x = 0 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { x = 0 }
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
index fd82da70a18..c0c0f966b68 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:14:13
+  --> $DIR/mut-ref-mut.rs:18:13
    |
 LL |     let Foo(mut a) = &Foo(0);
    |             ^^^^
@@ -9,7 +9,7 @@ LL |     let Foo(mut a) = &Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:19:13
+  --> $DIR/mut-ref-mut.rs:23:13
    |
 LL |     let Foo(mut a) = &mut Foo(0);
    |             ^^^^
@@ -19,7 +19,7 @@ LL |     let Foo(mut a) = &mut Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:24:15
+  --> $DIR/mut-ref-mut.rs:28:15
    |
 LL |     let [&mut mut x] = &[&mut 0];
    |               ^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr
new file mode 100644
index 00000000000..a856a0eaf2a
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr
@@ -0,0 +1,219 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:20:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:33:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                 |
+   |                 types differ in mutability
+   |
+   = note:      expected reference `&Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:45:23
+   |
+LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:56:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&mut Some(x)) = &Some(Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:114:11
+   |
+LL |     let [&&mut x] = &[&mut 0];
+   |           ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &[&mut 0];
+LL +     let [&x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:121:11
+   |
+LL |     let [&&mut x] = &mut [&mut 0];
+   |           ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &mut [&mut 0];
+LL +     let [&x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:128:11
+   |
+LL |     let [&&mut ref x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &[&mut 0];
+LL +     let [&ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:135:11
+   |
+LL |     let [&&mut ref x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &mut [&mut 0];
+LL +     let [&ref x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:142:11
+   |
+LL |     let [&&mut mut x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:149:11
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &mut [&mut 0];
+LL +     let [&mut x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:164:15
+   |
+LL |     let [&mut &x] = &[&mut 0];
+   |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:170:15
+   |
+LL |     let [&mut &ref x] = &[&mut 0];
+   |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &[&mut 0];
+LL +     let [&mut ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:176:15
+   |
+LL |     let [&mut &(mut x)] = &[&mut 0];
+   |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &[&mut 0];
+LL +     let [&mut mut x)] = &[&mut 0];
+   |
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
index 6726a726315..90510d23e66 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:12:17
+  --> $DIR/pattern-errors.rs:14:17
    |
 LL |     if let Some(&mut x) = &Some(&mut 0) {
    |                 ^^^^^
@@ -12,7 +12,7 @@ LL +     if let Some(&x) = &Some(&mut 0) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:18:17
+  --> $DIR/pattern-errors.rs:20:17
    |
 LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
    |                 ^^^^^
@@ -25,7 +25,7 @@ LL +     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:24:22
+  --> $DIR/pattern-errors.rs:26:22
    |
 LL |     if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
    |                      ^^^^^
@@ -38,7 +38,7 @@ LL +     if let Some(Some(&x)) = &Some(Some(&mut 0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^
@@ -51,7 +51,7 @@ LL +     if let Some(&Some(&_)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^
@@ -64,7 +64,7 @@ LL +     if let Some(&Some(&_)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^
@@ -77,7 +77,7 @@ LL +     if let Some(&Some(x)) = &Some(Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:147:10
+  --> $DIR/pattern-errors.rs:158:10
    |
 LL |     let [&mut x] = &[&mut 0];
    |          ^^^^^
@@ -90,7 +90,7 @@ LL +     let [&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:153:10
+  --> $DIR/pattern-errors.rs:164:10
    |
 LL |     let [&mut &x] = &[&mut 0];
    |          ^^^^^
@@ -103,7 +103,7 @@ LL +     let [&&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:159:10
+  --> $DIR/pattern-errors.rs:170:10
    |
 LL |     let [&mut &ref x] = &[&mut 0];
    |          ^^^^^
@@ -116,7 +116,7 @@ LL +     let [&&ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:165:10
+  --> $DIR/pattern-errors.rs:176:10
    |
 LL |     let [&mut &(mut x)] = &[&mut 0];
    |          ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
index c07c2972cd0..5e677445644 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
@@ -1,170 +1,181 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must
 //! be separate from cases caught by MIR borrowck or the latter errors may not be emitted.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut x) = &Some(&mut 0) {
         //[classic2024]~^ ERROR: mismatched types
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(structural2024)] let _: &u32 = x;
     }
     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-        //[stable2021,classic2024]~^ ERROR: mismatched types
-        //[stable2021]~| expected integer, found `&_`
+        //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        let _: u32 = x;
+        #[cfg(structural2024)] let _: u32 = x;
     }
     if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
         //[classic2024]~^ ERROR: mismatched types
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(structural2024)] let _: &u32 = x;
     }
 
     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
         //~^ ERROR: mismatched types
-        //[stable2021]~| types differ in mutability
+        //[stable2021,classic2021,structural2021]~| types differ in mutability
         //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
-    if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-        //[stable2021,structural2024]~^ ERROR: mismatched types
+    if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+        //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
         //[stable2021]~| types differ in mutability
+        //[classic2021,structural2021]~| expected integer, found `&mut _`
         //[structural2024]~| cannot match inherited `&` with `&mut` pattern
+        #[cfg(classic2024)] let _: u32 = x;
     }
     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
         //~^ ERROR: mismatched types
-        //[stable2021]~| expected integer, found `&mut _`
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&mut _`
         //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
-    if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
-        //[stable2021,structural2024]~^ ERROR: mismatched types
+    if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+        //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
         //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_`
-        //[structural2024]~| cannot match inherited `&` with `&mut` pattern
+        //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+        #[cfg(any(classic2021, classic2024))] let _: u32 = x;
     }
     if let Some(&mut Some(x)) = &Some(Some(0)) {
         //~^ ERROR: mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&mut _`
-        //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
 }
 
 fn structural_errors_0() {
     let &[&mut x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut ref x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: &u32 = x;
 
     let &[&mut ref x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: &u32 = x;
 
     let &[&mut mut x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut mut x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 }
 
 fn structural_errors_1() {
     let [&(mut x)] = &[&0];
     //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(classic2024)] let _: &u32 = x;
 
     let [&(mut x)] = &mut [&0];
     //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(classic2024)] let _: &u32 = x;
 }
 
 fn structural_errors_2() {
     let [&&mut x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut ref x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(classic2024)] let _: &u32 = x;
 
     let [&&mut ref x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(classic2024)] let _: &u32 = x;
 
     let [&&mut mut x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut mut x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 }
 
 fn classic_errors_0() {
     let [&mut x] = &[&mut 0];
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(structural2024)] let _: &u32 = x;
 
     let [&mut &x] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(structural2024)] let _: u32 = x;
 
     let [&mut &ref x] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 
     let [&mut &(mut x)] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(structural2024)] let _: u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
index ad19b122c20..76e6d2f562a 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:18:27
+  --> $DIR/pattern-errors.rs:20:27
    |
 LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
    |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
@@ -15,7 +15,7 @@ LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -26,9 +26,9 @@ LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:36:17
+  --> $DIR/pattern-errors.rs:38:17
    |
-LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
    |                 ^^^^^^^^^^^^^    ------------------- this expression has type `&Option<&mut Option<{integer}>>`
    |                 |
    |                 types differ in mutability
@@ -37,7 +37,7 @@ LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
@@ -48,9 +48,9 @@ LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:46:17
+  --> $DIR/pattern-errors.rs:50:17
    |
-LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
    |                 ^^^^^^^^^^^^^^^^^^^    ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
    |                 |
    |                 expected `Option<&mut Option<{integer}>>`, found `&_`
@@ -59,7 +59,7 @@ LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
@@ -70,7 +70,7 @@ LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -80,7 +80,7 @@ LL |     let &[&mut x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^^
@@ -91,7 +91,7 @@ LL +     let &[x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:65:9
+  --> $DIR/pattern-errors.rs:70:9
    |
 LL |     let &[&mut x] = &mut &mut [0];
    |         ^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -102,7 +102,7 @@ LL |     let &[&mut x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -112,7 +112,7 @@ LL |     let &[&mut ref x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^^^^^^
@@ -123,7 +123,7 @@ LL +     let &[ref x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:77:9
+  --> $DIR/pattern-errors.rs:82:9
    |
 LL |     let &[&mut ref x] = &mut &mut [0];
    |         ^^^^^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -134,7 +134,7 @@ LL |     let &[&mut ref x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -144,7 +144,7 @@ LL |     let &[&mut mut x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^^^^^^
@@ -155,7 +155,7 @@ LL +     let &[mut x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:89:9
+  --> $DIR/pattern-errors.rs:94:9
    |
 LL |     let &[&mut mut x] = &mut &mut [0];
    |         ^^^^^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -166,7 +166,7 @@ LL |     let &[&mut mut x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:109:10
+  --> $DIR/pattern-errors.rs:114:10
    |
 LL |     let [&&mut x] = &[&mut 0];
    |          ^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -177,7 +177,7 @@ LL |     let [&&mut x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:115:10
+  --> $DIR/pattern-errors.rs:121:10
    |
 LL |     let [&&mut x] = &mut [&mut 0];
    |          ^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -188,7 +188,7 @@ LL |     let [&&mut x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:121:10
+  --> $DIR/pattern-errors.rs:128:10
    |
 LL |     let [&&mut ref x] = &[&mut 0];
    |          ^^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -199,7 +199,7 @@ LL |     let [&&mut ref x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:127:10
+  --> $DIR/pattern-errors.rs:135:10
    |
 LL |     let [&&mut ref x] = &mut [&mut 0];
    |          ^^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -210,7 +210,7 @@ LL |     let [&&mut ref x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:133:10
+  --> $DIR/pattern-errors.rs:142:10
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |          ^^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -221,7 +221,7 @@ LL |     let [&&mut mut x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:139:10
+  --> $DIR/pattern-errors.rs:149:10
    |
 LL |     let [&&mut mut x] = &mut [&mut 0];
    |          ^^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -232,7 +232,7 @@ LL |     let [&&mut mut x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:153:15
+  --> $DIR/pattern-errors.rs:164:15
    |
 LL |     let [&mut &x] = &[&mut 0];
    |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -248,7 +248,7 @@ LL +     let [&mut x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:159:15
+  --> $DIR/pattern-errors.rs:170:15
    |
 LL |     let [&mut &ref x] = &[&mut 0];
    |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -264,7 +264,7 @@ LL +     let [&mut ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:165:15
+  --> $DIR/pattern-errors.rs:176:15
    |
 LL |     let [&mut &(mut x)] = &[&mut 0];
    |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr
new file mode 100644
index 00000000000..1ca6bff3f38
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr
@@ -0,0 +1,310 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:20:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:33:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                 |
+   |                 types differ in mutability
+   |
+   = note:      expected reference `&Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:45:23
+   |
+LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:50:28
+   |
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+   |                            ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+LL +     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:56:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&mut Some(x)) = &Some(Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:64:11
+   |
+LL |     let &[&mut x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut x] = &&mut [0];
+LL +     let &[&x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:70:11
+   |
+LL |     let &[&mut x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut x] = &mut &mut [0];
+LL +     let &[&x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:76:11
+   |
+LL |     let &[&mut ref x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut ref x] = &&mut [0];
+LL +     let &[&ref x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:82:11
+   |
+LL |     let &[&mut ref x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut ref x] = &mut &mut [0];
+LL +     let &[&ref x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:88:11
+   |
+LL |     let &[&mut mut x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut mut x] = &&mut [0];
+LL +     let &[&mut x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:94:11
+   |
+LL |     let &[&mut mut x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut mut x] = &mut &mut [0];
+LL +     let &[&mut x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:114:11
+   |
+LL |     let [&&mut x] = &[&mut 0];
+   |           ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &[&mut 0];
+LL +     let [&x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:121:11
+   |
+LL |     let [&&mut x] = &mut [&mut 0];
+   |           ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &mut [&mut 0];
+LL +     let [&x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:128:11
+   |
+LL |     let [&&mut ref x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &[&mut 0];
+LL +     let [&ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:135:11
+   |
+LL |     let [&&mut ref x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &mut [&mut 0];
+LL +     let [&ref x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:142:11
+   |
+LL |     let [&&mut mut x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:149:11
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &mut [&mut 0];
+LL +     let [&mut x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:164:15
+   |
+LL |     let [&mut &x] = &[&mut 0];
+   |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:170:15
+   |
+LL |     let [&mut &ref x] = &[&mut 0];
+   |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &[&mut 0];
+LL +     let [&mut ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:176:15
+   |
+LL |     let [&mut &(mut x)] = &[&mut 0];
+   |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &[&mut 0];
+LL +     let [&mut mut x)] = &[&mut 0];
+   |
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
index fdf48a5a71b..3658893df9c 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^
@@ -12,20 +12,20 @@ LL +     if let Some(&Some(&_)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:36:23
+  --> $DIR/pattern-errors.rs:38:23
    |
-LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
    |                       ^^^^^
    |
    = note: cannot match inherited `&` with `&mut` pattern
 help: replace this `&mut` pattern with `&`
    |
-LL -     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-LL +     if let Some(&Some(&_)) = &Some(&mut Some(0)) {
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^
@@ -38,20 +38,20 @@ LL +     if let Some(&Some(&_)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:46:28
+  --> $DIR/pattern-errors.rs:50:28
    |
-LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
    |                            ^^^^^
    |
    = note: cannot match inherited `&` with `&mut` pattern
 help: replace this `&mut` pattern with `&`
    |
-LL -     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
-LL +     if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) {
+LL -     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+LL +     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^
@@ -64,7 +64,7 @@ LL +     if let Some(&Some(x)) = &Some(Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^
@@ -77,7 +77,7 @@ LL +     let &[&x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:65:11
+  --> $DIR/pattern-errors.rs:70:11
    |
 LL |     let &[&mut x] = &mut &mut [0];
    |           ^^^^^
@@ -90,7 +90,7 @@ LL +     let &[&x] = &mut &mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^
@@ -103,7 +103,7 @@ LL +     let &[&ref x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:77:11
+  --> $DIR/pattern-errors.rs:82:11
    |
 LL |     let &[&mut ref x] = &mut &mut [0];
    |           ^^^^^
@@ -116,7 +116,7 @@ LL +     let &[&ref x] = &mut &mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^
@@ -129,7 +129,7 @@ LL +     let &[&mut x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:89:11
+  --> $DIR/pattern-errors.rs:94:11
    |
 LL |     let &[&mut mut x] = &mut &mut [0];
    |           ^^^^^
@@ -142,7 +142,7 @@ LL +     let &[&mut x] = &mut &mut [0];
    |
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/pattern-errors.rs:97:12
+  --> $DIR/pattern-errors.rs:102:12
    |
 LL |     let [&(mut x)] = &[&0];
    |            ^^^^
@@ -152,7 +152,7 @@ LL |     let [&(mut x)] = &[&0];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/pattern-errors.rs:102:12
+  --> $DIR/pattern-errors.rs:107:12
    |
 LL |     let [&(mut x)] = &mut [&0];
    |            ^^^^
@@ -162,7 +162,7 @@ LL |     let [&(mut x)] = &mut [&0];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:109:11
+  --> $DIR/pattern-errors.rs:114:11
    |
 LL |     let [&&mut x] = &[&mut 0];
    |           ^^^^^
@@ -175,7 +175,7 @@ LL +     let [&&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:115:11
+  --> $DIR/pattern-errors.rs:121:11
    |
 LL |     let [&&mut x] = &mut [&mut 0];
    |           ^^^^^
@@ -188,7 +188,7 @@ LL +     let [&&x] = &mut [&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:121:11
+  --> $DIR/pattern-errors.rs:128:11
    |
 LL |     let [&&mut ref x] = &[&mut 0];
    |           ^^^^^
@@ -201,7 +201,7 @@ LL +     let [&&ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:127:11
+  --> $DIR/pattern-errors.rs:135:11
    |
 LL |     let [&&mut ref x] = &mut [&mut 0];
    |           ^^^^^
@@ -214,7 +214,7 @@ LL +     let [&&ref x] = &mut [&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:133:11
+  --> $DIR/pattern-errors.rs:142:11
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |           ^^^^^
@@ -227,7 +227,7 @@ LL +     let [&&mut x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:139:11
+  --> $DIR/pattern-errors.rs:149:11
    |
 LL |     let [&&mut mut x] = &mut [&mut 0];
    |           ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr
new file mode 100644
index 00000000000..1dda2dca4a4
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
+   |
+LL |     let [ref mut x] = &[0];
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
index 56125be2d6f..44cb005a748 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:10
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |          ^^^^^
@@ -12,14 +12,14 @@ LL +     let [&ref x] = &[&mut 0];
    |
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:9
    |
 LL |     let [ref mut x] = &[0];
    |         ^^^^^^^^^^^ this matches on type `&_`
@@ -29,20 +29,20 @@ LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &[0];
    |          ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
    |
 LL |     let [ref x] = &[0];
    |         ^^^^^^^ this matches on type `&_`
@@ -52,14 +52,14 @@ LL |     let &[ref x] = &[0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref x] = &mut [0];
    |          ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
    |
 LL |     let [ref x] = &mut [0];
    |         ^^^^^^^ this matches on type `&mut _`
@@ -69,14 +69,14 @@ LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:10
    |
 LL |     let [ref mut x] = &mut [0];
    |          ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:9
    |
 LL |     let [ref mut x] = &mut [0];
    |         ^^^^^^^^^^^ this matches on type `&mut _`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
index 4e048570c33..ea6f028fe4b 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
@@ -1,35 +1,37 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Tests for errors from binding with `ref x` under a by-ref default binding mode in edition 2024.
 //! These can't be in the same body as tests for other errors, since they're emitted during THIR
 //! construction. The errors on stable edition 2021 Rust are unrelated.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 /// These only fail on the eat-inner variant of the new edition 2024 pattern typing rules.
 /// The eat-outer variant eats the inherited reference, so binding with `ref` isn't a problem.
 fn errors_from_eating_the_real_reference() {
     let [&ref x] = &[&0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&ref x] = &mut [&0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&mut ref x] = &mut [&mut 0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&mut ref mut x] = &mut [&mut 0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &mut u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &mut u32 = x;
     #[cfg(classic2024)] let _: &mut &mut u32 = x;
 }
 
@@ -40,12 +42,14 @@ fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() {
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&ref x] = &mut [&mut 0];
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 }
 
@@ -55,7 +59,7 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() {
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 }
 
 /// These should be errors in all editions. In edition 2024, they should be caught by the pattern
@@ -74,13 +78,13 @@ fn borrowck_errors_in_old_editions() {
 pub fn main() {
     let [ref x] = &[0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 
     let [ref x] = &mut [0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 
     let [ref mut x] = &mut [0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &mut u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &mut u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
index 26095d84605..2ec6650dd7d 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:10
    |
 LL |     let [&ref x] = &[&mut 0];
    |          ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -15,7 +15,7 @@ LL +     let [ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:10
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |          ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -31,7 +31,7 @@ LL +     let [ref x] = &mut [&mut 0];
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr
new file mode 100644
index 00000000000..1dda2dca4a4
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
+   |
+LL |     let [ref mut x] = &[0];
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
index 31930e8c033..6f62ad06cc4 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
@@ -1,12 +1,12 @@
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:17:11
    |
 LL |     let [&ref x] = &[&0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:15:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:17:9
    |
 LL |     let [&ref x] = &[&0];
    |         ^^^^^^^^ this matches on type `&_`
@@ -16,14 +16,14 @@ LL |     let &[&ref x] = &[&0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:22:11
    |
 LL |     let [&ref x] = &mut [&0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:20:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:22:9
    |
 LL |     let [&ref x] = &mut [&0];
    |         ^^^^^^^^ this matches on type `&mut _`
@@ -33,14 +33,14 @@ LL |     let &mut [&ref x] = &mut [&0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15
    |
 LL |     let [&mut ref x] = &mut [&mut 0];
    |               ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:25:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:27:9
    |
 LL |     let [&mut ref x] = &mut [&mut 0];
    |         ^^^^^^^^^^^^ this matches on type `&mut _`
@@ -50,14 +50,14 @@ LL |     let &mut [&mut ref x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:32:15
    |
 LL |     let [&mut ref mut x] = &mut [&mut 0];
    |               ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:30:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:32:9
    |
 LL |     let [&mut ref mut x] = &mut [&mut 0];
    |         ^^^^^^^^^^^^^^^^ this matches on type `&mut _`
@@ -67,14 +67,14 @@ LL |     let &mut [&mut ref mut x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:11
    |
 LL |     let [&ref x] = &[&mut 0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:9
    |
 LL |     let [&ref x] = &[&mut 0];
    |         ^^^^^^^^ this matches on type `&_`
@@ -84,14 +84,14 @@ LL |     let &[&ref x] = &[&mut 0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:11
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:9
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |         ^^^^^^^^ this matches on type `&mut _`
@@ -101,14 +101,14 @@ LL |     let &mut [&ref x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:15
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |               ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:9
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |         ^^^^^^^^^^^^ this matches on type `&_`
@@ -118,14 +118,14 @@ LL |     let &[&mut ref x] = &[&mut 0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:9
    |
 LL |     let [ref mut x] = &[0];
    |         ^^^^^^^^^^^ this matches on type `&_`
@@ -135,20 +135,20 @@ LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &[0];
    |          ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
    |
 LL |     let [ref x] = &[0];
    |         ^^^^^^^ this matches on type `&_`
@@ -158,14 +158,14 @@ LL |     let &[ref x] = &[0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref x] = &mut [0];
    |          ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
    |
 LL |     let [ref x] = &mut [0];
    |         ^^^^^^^ this matches on type `&mut _`
@@ -175,14 +175,14 @@ LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:10
    |
 LL |     let [ref mut x] = &mut [0];
    |          ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:9
    |
 LL |     let [ref mut x] = &mut [0];
    |         ^^^^^^^^^^^ this matches on type `&mut _`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr
new file mode 100644
index 00000000000..8127ca92e02
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr
@@ -0,0 +1,51 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
+   |
+LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
+   |
+LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
+   |
+LL |     let &pat!(x) = &mut 0;
+   |         -     ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -         ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -                    ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11
+   |
+LL |     let &[x] = &mut &mut [0];
+   |         - ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
index c01784d5076..57de9cb4c10 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &mut pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &mut (ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &mut [x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
index 5e98b77be40..8127ca92e02 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 -             ^
@@ -7,7 +7,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            -                  ^
@@ -15,7 +15,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
    |
 LL |     let &pat!(x) = &mut 0;
    |         -     ^
@@ -23,7 +23,7 @@ LL |     let &pat!(x) = &mut 0;
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -         ^
@@ -31,7 +31,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -                    ^
@@ -39,7 +39,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:11
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11
    |
 LL |     let &[x] = &mut &mut [0];
    |         - ^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
index fe40dabb553..277ff90b673 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &(ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &[x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
index 72c6c05e184..5fbaacd7281 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:17
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:17
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 ^^^^^^^^^^^^^^^^    ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -10,7 +10,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:12
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:12
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            ^^^^^^^^^^^^^^^^^^^^^^   ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -21,7 +21,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:9
    |
 LL |     let &pat!(x) = &mut 0;
    |         ^^^^^^^^   ------ this expression has type `&mut {integer}`
@@ -32,7 +32,7 @@ LL |     let &pat!(x) = &mut 0;
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:9
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         ^^^^^^^^^^^^^^^^^^^^^^^   ------------------ this expression has type `&mut (bool, bool)`
@@ -43,7 +43,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:9
    |
 LL |     let &[x] = &mut &mut [0];
    |         ^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr
new file mode 100644
index 00000000000..e735cfed249
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr
@@ -0,0 +1,43 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
+   |
+LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
+   |
+LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
+   |
+LL |     let &pat!(x) = &mut 0;
+   |         -     ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -         ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -                    ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
index 4ee849b38c5..bcde4b90f59 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &mut pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &mut (ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &[x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
index 69cb6c438b6..e735cfed249 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 -             ^
@@ -7,7 +7,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            -                  ^
@@ -15,7 +15,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
    |
 LL |     let &pat!(x) = &mut 0;
    |         -     ^
@@ -23,7 +23,7 @@ LL |     let &pat!(x) = &mut 0;
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -         ^
@@ -31,7 +31,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -                    ^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
deleted file mode 100644
index ab3264704ac..00000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ run-pass
-//@ edition: 2021
-//@ revisions: classic structural
-#![allow(incomplete_features)]
-#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
-
-pub fn main() {
-    #[cfg(structural)]
-    if let &Some(Some(x)) = &Some(&mut Some(0)) {
-        let _: &u32 = x;
-    }
-
-    if let Some(&x) = Some(&mut 0) {
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
deleted file mode 100644
index d28567f2859..00000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ edition: 2021
-#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
-pub fn main() {
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&x)) = &Some(Some(&0)) {
-        let _: &u32 = x;
-        //~^ ERROR: mismatched types
-    }
-    if let Some(Some(&&x)) = &Some(Some(&0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&Some(x)) = &Some(Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
deleted file mode 100644
index 0158ed0f423..00000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
+++ /dev/null
@@ -1,133 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:5:22
-   |
-LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
-   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&x)) = &Some(&Some(0)) {
-LL +     if let Some(Some(x)) = &Some(&Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:10:23
-   |
-LL |         let _: &u32 = x;
-   |                ----   ^ expected `&u32`, found integer
-   |                |
-   |                expected due to this
-   |
-help: consider borrowing here
-   |
-LL |         let _: &u32 = &x;
-   |                       +
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:13:23
-   |
-LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
-   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
-   |                       |
-   |                       expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
-LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:17:17
-   |
-LL |     if let Some(&Some(x)) = &Some(Some(0)) {
-   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&_`
-   |
-   = note:   expected enum `Option<{integer}>`
-           found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&mut _`
-   |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-LL +     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:25:22
-   |
-LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
-   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&x)) = &Some(&Some(0)) {
-LL +     if let Some(Some(x)) = &Some(&Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:29:27
-   |
-LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
-   |                           |
-   |                           expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23
-   |
-LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
-   |                       |
-   |                       expected integer, found `&mut _`
-   |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23
-   |
-LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-   |                       ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
-   |
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr
new file mode 100644
index 00000000000..f8c2bd9a921
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr
@@ -0,0 +1,122 @@
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:32:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:63:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
+   |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:82:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+   |                       ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:88:23
+   |
+LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+   |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:123:15
+   |
+LL |     let [&mut &x] = &mut [&0];
+   |               ^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &mut [&0];
+LL +     let [&mut x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:129:15
+   |
+LL |     let [&mut &ref x] = &mut [&0];
+   |               ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &mut [&0];
+LL +     let [&mut ref x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:135:15
+   |
+LL |     let [&mut &(mut x)] = &mut [&0];
+   |               ^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &mut [&0];
+LL +     let [&mut mut x)] = &mut [&0];
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/well-typed-edition-2024.rs:109:19
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |                   ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0596.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
index 3114b9d3bf8..62c1c28022b 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-pass
@@ -7,8 +9,8 @@
 //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we
 //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests.
 #![allow(incomplete_features, unused_mut)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     // Tests not using match ergonomics. These should always succeed with the same bindings.
@@ -18,110 +20,121 @@ pub fn main() {
 
     // Tests for differences in how many layers of reference are eaten by reference patterns
     if let Some(Some(&x)) = &Some(Some(&0)) {
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
     }
     if let Some(&Some(x)) = &mut Some(&Some(0)) {
         // This additionally tests that `&` patterns can eat inherited `&mut` refs.
         // This is possible on stable when the real reference being eaten is of a `&` type.
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
     }
     if let Some(Some(&&x)) = &Some(Some(&0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for eating a lone inherited reference
     if let Some(Some(&x)) = &Some(&Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(x)) = &Some(Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected integer, found `&mut _`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for `&` patterns matching real `&mut` reference types
     if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| types differ in mutability
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for eating only one layer and also eating a lone inherited reference
     if let Some(&Some(&x)) = &Some(&Some(0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for `&` matching a lone inherited possibly-`&mut` reference
     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(x)) = &mut Some(Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests eating one layer, eating a lone inherited ref, and `&` eating `&mut` (realness varies)
     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
-        //[stable2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~^ mismatched types
         //[stable2021]~| types differ in mutability
-        let _: u32 = x;
+        //[classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
-    // Tests for eat-inner rulesets matching on the outer reference if matching on the inner
-    // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`:
+    // Tests for eat-inner and eat-both rulesets matching on the outer reference if matching on the
+    // inner reference causes a mutability mismatch. i.e. tests for "fallback-to-outer" deref rules.
     let [&mut x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut ref x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &&u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &&u32 = x;
 
-    let [&mut ref mut x] = &mut [&0];
-    //[stable2021]~^ mismatched types
-    //[stable2021]~| types differ in mutability
-    let _: &mut &u32 = x;
+    fn borrowck_error_on_structural2021() {
+        let [&mut ref mut x] = &mut [&0];
+        //[stable2021]~^ mismatched types
+        //[stable2021]~| types differ in mutability
+        //[classic2021,structural2021]~^^^ cannot borrow data in a `&` reference as mutable
+        #[cfg(any(classic2024, structural2024))] let _: &mut &u32 = x;
+    }
+    borrowck_error_on_structural2021();
 
     let [&mut mut x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut &x] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: u32 = x;
 
     let [&mut &ref x] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut &(mut x)] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
index b1a8024397b..adb47172f34 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:30:23
+  --> $DIR/well-typed-edition-2024.rs:32:23
    |
 LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
    |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
@@ -15,7 +15,7 @@ LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:37:22
+  --> $DIR/well-typed-edition-2024.rs:39:22
    |
 LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
    |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -31,7 +31,7 @@ LL +     if let Some(Some(x)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:42:17
+  --> $DIR/well-typed-edition-2024.rs:44:17
    |
 LL |     if let Some(&Some(x)) = &Some(Some(0)) {
    |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
@@ -42,7 +42,7 @@ LL |     if let Some(&Some(x)) = &Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:47:22
+  --> $DIR/well-typed-edition-2024.rs:49:22
    |
 LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
@@ -52,7 +52,7 @@ LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:47:22
+  --> $DIR/well-typed-edition-2024.rs:49:22
    |
 LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    |                      ^^^^^^
@@ -63,7 +63,7 @@ LL +     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:54:23
+  --> $DIR/well-typed-edition-2024.rs:56:23
    |
 LL |     if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
    |                       ^^     ------------------- this expression has type `Option<&Option<&mut {integer}>>`
@@ -79,7 +79,7 @@ LL +     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:61:23
+  --> $DIR/well-typed-edition-2024.rs:63:23
    |
 LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
    |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -95,7 +95,7 @@ LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:68:17
+  --> $DIR/well-typed-edition-2024.rs:70:17
    |
 LL |     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
    |                 ^^^^^^^^^^^^^^^    ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
@@ -106,7 +106,7 @@ LL |     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:73:17
+  --> $DIR/well-typed-edition-2024.rs:75:17
    |
 LL |     if let Some(&Some(x)) = &mut Some(Some(0)) {
    |                 ^^^^^^^^    ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -117,7 +117,7 @@ LL |     if let Some(&Some(x)) = &mut Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:80:17
+  --> $DIR/well-typed-edition-2024.rs:82:17
    |
 LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |                 ^^^^^^^^^    ------------------- this expression has type `&Option<&mut Option<{integer}>>`
@@ -128,7 +128,7 @@ LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:85:23
+  --> $DIR/well-typed-edition-2024.rs:88:23
    |
 LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
    |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
@@ -144,7 +144,7 @@ LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:93:10
+  --> $DIR/well-typed-edition-2024.rs:96:10
    |
 LL |     let [&mut x] = &mut [&0];
    |          ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -154,7 +154,7 @@ LL |     let [&mut x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:93:10
+  --> $DIR/well-typed-edition-2024.rs:96:10
    |
 LL |     let [&mut x] = &mut [&0];
    |          ^^^^^^
@@ -165,7 +165,7 @@ LL +     let [x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:98:10
+  --> $DIR/well-typed-edition-2024.rs:102:10
    |
 LL |     let [&mut ref x] = &mut [&0];
    |          ^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -175,7 +175,7 @@ LL |     let [&mut ref x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:98:10
+  --> $DIR/well-typed-edition-2024.rs:102:10
    |
 LL |     let [&mut ref x] = &mut [&0];
    |          ^^^^^^^^^^
@@ -186,28 +186,7 @@ LL +     let [ref x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:103:10
-   |
-LL |     let [&mut ref mut x] = &mut [&0];
-   |          ^^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
-   |          |
-   |          types differ in mutability
-   |
-   = note:      expected reference `&{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:103:10
-   |
-LL |     let [&mut ref mut x] = &mut [&0];
-   |          ^^^^^^^^^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     let [&mut ref mut x] = &mut [&0];
-LL +     let [ref mut x] = &mut [&0];
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:108:10
+  --> $DIR/well-typed-edition-2024.rs:117:10
    |
 LL |     let [&mut mut x] = &mut [&0];
    |          ^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -217,7 +196,7 @@ LL |     let [&mut mut x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:108:10
+  --> $DIR/well-typed-edition-2024.rs:117:10
    |
 LL |     let [&mut mut x] = &mut [&0];
    |          ^^^^^^^^^^
@@ -228,7 +207,7 @@ LL +     let [mut x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:113:10
+  --> $DIR/well-typed-edition-2024.rs:123:10
    |
 LL |     let [&mut &x] = &mut [&0];
    |          ^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -239,7 +218,7 @@ LL |     let [&mut &x] = &mut [&0];
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:118:10
+  --> $DIR/well-typed-edition-2024.rs:129:10
    |
 LL |     let [&mut &ref x] = &mut [&0];
    |          ^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -250,7 +229,7 @@ LL |     let [&mut &ref x] = &mut [&0];
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:123:10
+  --> $DIR/well-typed-edition-2024.rs:135:10
    |
 LL |     let [&mut &(mut x)] = &mut [&0];
    |          ^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -260,6 +239,27 @@ LL |     let [&mut &(mut x)] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:109:14
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |              ^^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |              |
+   |              types differ in mutability
+   |
+   = note:      expected reference `&{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/well-typed-edition-2024.rs:109:14
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |              ^^^^^^^^^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -         let [&mut ref mut x] = &mut [&0];
+LL +         let [ref mut x] = &mut [&0];
+   |
+
 error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr
new file mode 100644
index 00000000000..f8c2bd9a921
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr
@@ -0,0 +1,122 @@
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:32:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:63:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
+   |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:82:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+   |                       ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:88:23
+   |
+LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+   |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:123:15
+   |
+LL |     let [&mut &x] = &mut [&0];
+   |               ^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &mut [&0];
+LL +     let [&mut x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:129:15
+   |
+LL |     let [&mut &ref x] = &mut [&0];
+   |               ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &mut [&0];
+LL +     let [&mut ref x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:135:15
+   |
+LL |     let [&mut &(mut x)] = &mut [&0];
+   |               ^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &mut [&0];
+LL +     let [&mut mut x)] = &mut [&0];
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/well-typed-edition-2024.rs:109:19
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |                   ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0596.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
index 0a22e939496..bb4ecc09063 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
@@ -239,4 +239,15 @@ fn main() {
     assert_type_eq(b, &0u32);
     assert_type_eq(c, &[0u32]);
     assert_type_eq(d, 0u32);
+
+    // Test that we use the correct message and suggestion style when pointing inside expansions.
+    let &[migration_lint_macros::bind_ref!(a)] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    assert_type_eq(a, &0u32);
+
+    // Test that we use the correct span when labeling a `&` whose subpattern is from an expansion.
+    let &[&migration_lint_macros::bind_ref!(a)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
index 7a6f2269d44..2837c8d81db 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
@@ -239,4 +239,15 @@ fn main() {
     assert_type_eq(b, &0u32);
     assert_type_eq(c, &[0u32]);
     assert_type_eq(d, 0u32);
+
+    // Test that we use the correct message and suggestion style when pointing inside expansions.
+    let [migration_lint_macros::bind_ref!(a)] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    assert_type_eq(a, &0u32);
+
+    // Test that we use the correct span when labeling a `&` whose subpattern is from an expansion.
+    let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
index 191800df07a..6efda4f757f 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
@@ -562,5 +562,41 @@ help: make the implied reference patterns explicit
 LL |     let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
    |          +                       +
 
-error: aborting due to 29 previous errors
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/migration_lint.rs:244:10
+   |
+LL |     let [migration_lint_macros::bind_ref!(a)] = &[0];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:244:9
+   |
+LL |     let [migration_lint_macros::bind_ref!(a)] = &[0];
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+   = note: this error originates in the macro `migration_lint_macros::bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: make the implied reference pattern explicit
+   |
+LL |     let &[migration_lint_macros::bind_ref!(a)] = &[0];
+   |         +
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:249:10
+   |
+LL |     let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |          ^ reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:249:9
+   |
+LL |     let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference pattern explicit
+   |
+LL |     let &[&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |         +
+
+error: aborting due to 31 previous errors
 
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 453e53379fc..3ecf271599d 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -9,9 +9,9 @@
 // Make sure that these behaviors don't get inherited to children
 // spawned via std::process, since they're needed for traditional UNIX
 // filter behavior.
-// This test checks that `while echo y ; do : ; done | head` terminates
-// (instead of running forever), and that it does not print an error
-// message about a broken pipe.
+// This test checks that `yes` or `while echo y ; do : ; done | head`
+// terminates (instead of running forever), and that it does not print an
+// error message about a broken pipe.
 
 //@ ignore-vxworks no 'sh'
 //@ ignore-fuchsia no 'sh'
@@ -22,14 +22,21 @@ use std::process;
 use std::thread;
 
 fn main() {
-    // Just in case `yes` doesn't check for EPIPE...
+    // Just in case `yes` or `while-echo` doesn't check for EPIPE...
     thread::spawn(|| {
         thread::sleep_ms(5000);
         process::exit(1);
     });
+    // QNX Neutrino does not have `yes`. Therefore, use `while-echo` for `nto`
+    // and `yes` for other platforms.
+    let command = if cfg!(target_os = "nto") {
+        "while echo y ; do : ; done | head"
+    } else {
+        "yes | head"
+    };
     let output = process::Command::new("sh")
         .arg("-c")
-        .arg("while echo y ; do : ; done | head")
+        .arg(command)
         .output()
         .unwrap();
     assert!(output.status.success());
diff --git a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr
index 2e76333e26f..ca9ceeeeff3 100644
--- a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
    |
 LL | fn bar<'a, 'b>()
@@ -24,4 +24,4 @@ LL | fn bar<'a, 'b>()
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/regions/resolve-re-error-ice.stderr b/tests/ui/regions/resolve-re-error-ice.stderr
index 41c5f0fa92e..f463a97c5bc 100644
--- a/tests/ui/regions/resolve-re-error-ice.stderr
+++ b/tests/ui/regions/resolve-re-error-ice.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter '_ in generic type due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter '_ in generic type due to conflicting requirements
   --> $DIR/resolve-re-error-ice.rs:12:5
    |
 LL |     fn key_set(&self) -> Subject<'a, Keys<K, V>, (), R> {
@@ -34,4 +34,4 @@ LL | struct Subject<'a, T, V, R>(PhantomData<(&'a T, V, R)>);
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs
index 2b6bbf12650..011076882d2 100644
--- a/tests/ui/repr/16-bit-repr-c-enum.rs
+++ b/tests/ui/repr/16-bit-repr-c-enum.rs
@@ -2,7 +2,7 @@
 //@ revisions: avr msp430
 //
 //@ [avr] needs-llvm-components: avr
-//@ [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib
 //@ [msp430] needs-llvm-components: msp430
 //@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
 #![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)]
diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
index 8e8f1d159b7..204db30786e 100644
--- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
@@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout {
                abi: Align(4 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Uninhabited,
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: true,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Scalar(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=0,
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       size: Size(4 bytes),
+                       size: Size(8 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=1,
+                           },
+                           Union {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(8 bytes),
@@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
index 2cd0960ce3e..1fab00bf50c 100644
--- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
@@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Uninhabited,
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: true,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Scalar(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=0,
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       size: Size(1 bytes),
+                       size: Size(2 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=1,
+                           },
+                           Union {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(8 bytes),
@@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
index 8e8f1d159b7..204db30786e 100644
--- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
@@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout {
                abi: Align(4 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Uninhabited,
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: true,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Scalar(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=0,
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       size: Size(4 bytes),
+                       size: Size(8 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=1,
+                           },
+                           Union {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(8 bytes),
@@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
index 8e8f1d159b7..204db30786e 100644
--- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
@@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout {
                abi: Align(4 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Uninhabited,
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I32,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: true,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Scalar(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=0,
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       size: Size(4 bytes),
+                       size: Size(8 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(4 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I32,
+                                   false,
+                               ),
+                               valid_range: 0..=1,
+                           },
+                           Union {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(4 bytes),
@@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(8 bytes),
@@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr
index fa08b323dec..f852212deb9 100644
--- a/tests/ui/repr/repr-c-int-dead-variants.stderr
+++ b/tests/ui/repr/repr-c-int-dead-variants.stderr
@@ -4,7 +4,15 @@ error: layout_of(UnivariantU8) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Uninhabited,
+           abi: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       false,
+                   ),
+                   valid_range: 0..=0,
+               },
+           ),
            fields: Arbitrary {
                offsets: [
                    Size(0 bytes),
@@ -23,6 +31,7 @@ error: layout_of(UnivariantU8) = Layout {
                    valid_range: 0..=0,
                },
            ),
+           uninhabited: true,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -40,7 +49,15 @@ error: layout_of(UnivariantU8) = Layout {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Scalar(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=0,
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -50,6 +67,7 @@ error: layout_of(UnivariantU8) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -107,6 +125,7 @@ error: layout_of(TwoVariantsU8) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -119,12 +138,26 @@ error: layout_of(TwoVariantsU8) = Layout {
                tag_field: 0,
                variants: [
                    Layout {
-                       size: Size(1 bytes),
+                       size: Size(2 bytes),
                        align: AbiAndPrefAlign {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: ScalarPair(
+                           Initialized {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                               valid_range: 0..=1,
+                           },
+                           Union {
+                               value: Int(
+                                   I8,
+                                   false,
+                               ),
+                           },
+                       ),
                        fields: Arbitrary {
                            offsets: [
                                Size(1 bytes),
@@ -134,6 +167,7 @@ error: layout_of(TwoVariantsU8) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -171,6 +205,7 @@ error: layout_of(TwoVariantsU8) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                    valid_range: 0..=1,
                },
            ),
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Uninhabited,
+                       abi: Memory {
+                           sized: true,
+                       },
                        fields: Arbitrary {
                            offsets: [
                                Size(8 bytes),
@@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: true,
                        variants: Single {
                            index: 0,
                        },
@@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                            ],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs
new file mode 100644
index 00000000000..432e3c0b77e
--- /dev/null
+++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs
@@ -0,0 +1,123 @@
+// see also https://github.com/rust-lang/rust/issues/22692
+
+type Alias = Vec<u32>;
+
+mod foo {
+    fn bar() {}
+}
+
+fn main() {
+    let _ = String.new();
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = String.default;
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = Vec::<()>.with_capacity(1);
+    //~^ ERROR expected value, found struct `Vec`
+    //~| HELP use the path separator
+
+    let _ = Alias.new();
+    //~^ ERROR expected value, found type alias `Alias`
+    //~| HELP use the path separator
+
+    let _ = Alias.default;
+    //~^ ERROR expected value, found type alias `Alias`
+    //~| HELP use the path separator
+
+    let _ = foo.bar;
+    //~^ ERROR expected value, found module `foo`
+    //~| HELP use the path separator
+}
+
+macro_rules! Type {
+    () => {
+        ::std::cell::Cell
+        //~^ ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+    };
+    (alias) => {
+        Alias
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| ERROR expected value, found type alias `Alias`
+        //~| ERROR expected value, found type alias `Alias`
+    };
+}
+
+macro_rules! create {
+    (type method) => {
+        Vec.new()
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (type field) => {
+        Vec.new
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (macro method) => {
+        Type!().new(0)
+        //~^ HELP use the path separator
+    };
+    (macro method alias) => {
+        Type!(alias).new(0)
+        //~^ HELP use the path separator
+    };
+}
+
+macro_rules! check_ty {
+    ($Ty:ident) => {
+        $Ty.foo
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+macro_rules! check_ident {
+    ($Ident:ident) => {
+        Alias.$Ident
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+macro_rules! check_ty_ident {
+    ($Ty:ident, $Ident:ident) => {
+        $Ty.$Ident
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+
+fn interaction_with_macros() {
+    //
+    // Verify that we do not only suggest to replace `.` with `::` if the receiver is a
+    // macro call but that we also correctly suggest to surround it with angle brackets.
+    //
+
+    Type!().get();
+    //~^ HELP use the path separator
+
+    Type! {}.get;
+    //~^ HELP use the path separator
+
+    Type!(alias).get();
+    //~^ HELP use the path separator
+
+    Type! {alias}.get;
+    //~^ HELP use the path separator
+
+    //
+    // Ensure that the suggestion is shown for expressions inside of macro definitions.
+    //
+
+    let _ = create!(type method);
+    let _ = create!(type field);
+    let _ = create!(macro method);
+    let _ = create!(macro method alias);
+
+    let _ = check_ty!(Alias);
+    let _ = check_ident!(foo);
+    let _ = check_ty_ident!(Alias, foo);
+}
diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr
new file mode 100644
index 00000000000..d74814dd876
--- /dev/null
+++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr
@@ -0,0 +1,251 @@
+error[E0423]: expected value, found struct `String`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:10:13
+   |
+LL |     let _ = String.new();
+   |             ^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = String.new();
+LL +     let _ = String::new();
+   |
+
+error[E0423]: expected value, found struct `String`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:14:13
+   |
+LL |     let _ = String.default;
+   |             ^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = String.default;
+LL +     let _ = String::default;
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:18:13
+   |
+LL |     let _ = Vec::<()>.with_capacity(1);
+   |             ^^^^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Vec::<()>.with_capacity(1);
+LL +     let _ = Vec::<()>::with_capacity(1);
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:22:13
+   |
+LL |     let _ = Alias.new();
+   |             ^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Alias.new();
+LL +     let _ = Alias::new();
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:26:13
+   |
+LL |     let _ = Alias.default;
+   |             ^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Alias.default;
+LL +     let _ = Alias::default;
+   |
+
+error[E0423]: expected value, found module `foo`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:30:13
+   |
+LL |     let _ = foo.bar;
+   |             ^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = foo.bar;
+LL +     let _ = foo::bar;
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type!().get();
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type!().get();
+LL +     <Type!()>::get();
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type! {}.get;
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type! {}.get;
+LL +     <Type! {}>::get;
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     Type!(alias).get();
+   |     ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type!(alias).get();
+LL +     <Type!(alias)>::get();
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     Type! {alias}.get;
+   |     ------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type! {alias}.get;
+LL +     <Type! {alias}>::get;
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:52:9
+   |
+LL |         Vec.new()
+   |         ^^^
+...
+LL |     let _ = create!(type method);
+   |             -------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Vec.new()
+LL +         Vec::new()
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:57:9
+   |
+LL |         Vec.new
+   |         ^^^
+...
+LL |     let _ = create!(type field);
+   |             ------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Vec.new
+LL +         Vec::new
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     let _ = create!(macro method);
+   |             --------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Type!().new(0)
+LL +         <Type!()>::new(0)
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     let _ = create!(macro method alias);
+   |             --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Type!(alias).new(0)
+LL +         <Type!(alias)>::new(0)
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:73:9
+   |
+LL |         $Ty.foo
+   |         ^^^
+...
+LL |     let _ = check_ty!(Alias);
+   |             ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         $Ty.foo
+LL +         $Ty::foo
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:80:9
+   |
+LL |         Alias.$Ident
+   |         ^^^^^
+...
+LL |     let _ = check_ident!(foo);
+   |             ----------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Alias.$Ident
+LL +         <Alias>::$Ident
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:87:9
+   |
+LL |         $Ty.$Ident
+   |         ^^^
+...
+LL |     let _ = check_ty_ident!(Alias, foo);
+   |             --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ty_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         $Ty.$Ident
+LL +         <$Ty>::$Ident
+   |
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.rs b/tests/ui/resolve/enum-expected-value-suggest-variants.rs
new file mode 100644
index 00000000000..9f86a0a1ecc
--- /dev/null
+++ b/tests/ui/resolve/enum-expected-value-suggest-variants.rs
@@ -0,0 +1,58 @@
+enum Foo {
+    //~^ HELP consider importing this tuple variant
+    A(u32),
+    B(u32),
+}
+
+enum Bar {
+    C(u32),
+    D(u32),
+    E,
+    F,
+}
+
+fn main() {
+    let _: Foo = Foo(0);
+    //~^ ERROR expected function
+    //~| HELP try to construct one of the enum's variants
+
+    let _: Foo = Foo.A(0);
+    //~^ ERROR expected value, found enum `Foo`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Foo = Foo.Bad(0);
+    //~^ ERROR expected value, found enum `Foo`
+    //~| HELP the following enum variants are available
+
+    let _: Bar = Bar(0);
+    //~^ ERROR expected function
+    //~| HELP try to construct one of the enum's variants
+    //~| HELP you might have meant to construct one of the enum's non-tuple variants
+
+    let _: Bar = Bar.C(0);
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Bar = Bar.E;
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Bar = Bar.Bad(0);
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP you might have meant to use one of the following enum variants
+    //~| HELP alternatively, the following enum variants are also available
+
+    let _: Bar = Bar.Bad;
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP you might have meant to use one of the following enum variants
+    //~| HELP alternatively, the following enum variants are also available
+
+    match Foo::A(42) {
+        A(..) => {}
+        //~^ ERROR cannot find tuple struct or tuple variant `A` in this scope
+        Foo(..) => {}
+        //~^ ERROR expected tuple struct or tuple variant
+        //~| HELP try to match against one of the enum's variants
+        _ => {}
+    }
+}
diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.stderr b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr
new file mode 100644
index 00000000000..548a4c0e593
--- /dev/null
+++ b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr
@@ -0,0 +1,234 @@
+error[E0423]: expected value, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:19:18
+   |
+LL |     let _: Foo = Foo.A(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Foo = Foo.A(0);
+LL +     let _: Foo = Foo::A(0);
+   |
+
+error[E0423]: expected value, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:23:18
+   |
+LL |     let _: Foo = Foo.Bad(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: the following enum variants are available
+   |
+LL -     let _: Foo = Foo.Bad(0);
+LL +     let _: Foo = (Foo::A(/* fields */)).Bad(0);
+   |
+LL -     let _: Foo = Foo.Bad(0);
+LL +     let _: Foo = (Foo::B(/* fields */)).Bad(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:32:18
+   |
+LL |     let _: Bar = Bar.C(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Bar = Bar.C(0);
+LL +     let _: Bar = Bar::C(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:36:18
+   |
+LL |     let _: Bar = Bar.E;
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Bar = Bar.E;
+LL +     let _: Bar = Bar::E;
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:40:18
+   |
+LL |     let _: Bar = Bar.Bad(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: you might have meant to use one of the following enum variants
+   |
+LL |     let _: Bar = Bar::E.Bad(0);
+   |                     +++
+LL |     let _: Bar = Bar::F.Bad(0);
+   |                     +++
+help: alternatively, the following enum variants are also available
+   |
+LL -     let _: Bar = Bar.Bad(0);
+LL +     let _: Bar = (Bar::C(/* fields */)).Bad(0);
+   |
+LL -     let _: Bar = Bar.Bad(0);
+LL +     let _: Bar = (Bar::D(/* fields */)).Bad(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:45:18
+   |
+LL |     let _: Bar = Bar.Bad;
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: you might have meant to use one of the following enum variants
+   |
+LL |     let _: Bar = Bar::E.Bad;
+   |                     +++
+LL |     let _: Bar = Bar::F.Bad;
+   |                     +++
+help: alternatively, the following enum variants are also available
+   |
+LL -     let _: Bar = Bar.Bad;
+LL +     let _: Bar = (Bar::C(/* fields */)).Bad;
+   |
+LL -     let _: Bar = Bar.Bad;
+LL +     let _: Bar = (Bar::D(/* fields */)).Bad;
+   |
+
+error[E0531]: cannot find tuple struct or tuple variant `A` in this scope
+  --> $DIR/enum-expected-value-suggest-variants.rs:51:9
+   |
+LL |         A(..) => {}
+   |         ^ not found in this scope
+   |
+help: consider importing this tuple variant
+   |
+LL + use Foo::A;
+   |
+
+error[E0532]: expected tuple struct or tuple variant, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:53:9
+   |
+LL |         Foo(..) => {}
+   |         ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: try to match against one of the enum's variants
+   |
+LL |         Foo::A(..) => {}
+   |            +++
+LL |         Foo::B(..) => {}
+   |            +++
+
+error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:15:18
+   |
+LL |     let _: Foo = Foo(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: try to construct one of the enum's variants
+   |
+LL |     let _: Foo = Foo::A(0);
+   |                     +++
+LL |     let _: Foo = Foo::B(0);
+   |                     +++
+
+error[E0423]: expected function, tuple struct or tuple variant, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:27:18
+   |
+LL |     let _: Bar = Bar(0);
+   |                  ^^^
+   |
+   = help: you might have meant to construct one of the enum's non-tuple variants
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: try to construct one of the enum's variants
+   |
+LL |     let _: Bar = Bar::C(0);
+   |                     +++
+LL |     let _: Bar = Bar::D(0);
+   |                     +++
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0423, E0531, E0532.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/resolve/issue-22692.rs b/tests/ui/resolve/issue-22692.rs
deleted file mode 100644
index 31a76261408..00000000000
--- a/tests/ui/resolve/issue-22692.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-fn main() {
-    let _ = String.new();
-    //~^ ERROR expected value, found struct `String`
-    //~| HELP use the path separator
-
-    let _ = String.default;
-    //~^ ERROR expected value, found struct `String`
-    //~| HELP use the path separator
-
-    let _ = Vec::<()>.with_capacity(1);
-    //~^ ERROR expected value, found struct `Vec`
-    //~| HELP use the path separator
-}
-
-macro_rules! Type {
-    () => {
-        ::std::cell::Cell
-        //~^ ERROR expected value, found struct `std::cell::Cell`
-        //~| ERROR expected value, found struct `std::cell::Cell`
-        //~| ERROR expected value, found struct `std::cell::Cell`
-    };
-}
-
-macro_rules! create {
-    (type method) => {
-        Vec.new()
-        //~^ ERROR expected value, found struct `Vec`
-        //~| HELP use the path separator
-    };
-    (type field) => {
-        Vec.new
-        //~^ ERROR expected value, found struct `Vec`
-        //~| HELP use the path separator
-    };
-    (macro method) => {
-        Type!().new(0)
-        //~^ HELP use the path separator
-    };
-}
-
-fn interaction_with_macros() {
-    //
-    // Verify that we do not only suggest to replace `.` with `::` if the receiver is a
-    // macro call but that we also correctly suggest to surround it with angle brackets.
-    //
-
-    Type!().get();
-    //~^ HELP use the path separator
-
-    Type! {}.get;
-    //~^ HELP use the path separator
-
-    //
-    // Ensure that the suggestion is shown for expressions inside of macro definitions.
-    //
-
-    let _ = create!(type method);
-    let _ = create!(type field);
-    let _ = create!(macro method);
-}
diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr
deleted file mode 100644
index 546f12b35c1..00000000000
--- a/tests/ui/resolve/issue-22692.stderr
+++ /dev/null
@@ -1,119 +0,0 @@
-error[E0423]: expected value, found struct `String`
-  --> $DIR/issue-22692.rs:2:13
-   |
-LL |     let _ = String.new();
-   |             ^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = String.new();
-LL +     let _ = String::new();
-   |
-
-error[E0423]: expected value, found struct `String`
-  --> $DIR/issue-22692.rs:6:13
-   |
-LL |     let _ = String.default;
-   |             ^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = String.default;
-LL +     let _ = String::default;
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:10:13
-   |
-LL |     let _ = Vec::<()>.with_capacity(1);
-   |             ^^^^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = Vec::<()>.with_capacity(1);
-LL +     let _ = Vec::<()>::with_capacity(1);
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     Type!().get();
-   |     ------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -     Type!().get();
-LL +     <Type!()>::get();
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     Type! {}.get;
-   |     -------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -     Type! {}.get;
-LL +     <Type! {}>::get;
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:26:9
-   |
-LL |         Vec.new()
-   |         ^^^
-...
-LL |     let _ = create!(type method);
-   |             -------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Vec.new()
-LL +         Vec::new()
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:31:9
-   |
-LL |         Vec.new
-   |         ^^^
-...
-LL |     let _ = create!(type field);
-   |             ------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Vec.new
-LL +         Vec::new
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     let _ = create!(macro method);
-   |             --------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Type!().new(0)
-LL +         <Type!()>::new(0)
-   |
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-simd-abi-checks.rs
index cb3128a890f..396e9bf1318 100644
--- a/tests/ui/sse-abi-checks.rs
+++ b/tests/ui/sse-simd-abi-checks.rs
@@ -1,7 +1,8 @@
 //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled
-//! on a target, but disabled in this file via a `-C` flag.
+//! on a target via the base CPU, but disabled in this file via a `-C` flag.
+//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu
+//@ compile-flags: -Ctarget-cpu=pentium4 -C target-feature=-sse,-sse2
 //@ add-core-stubs
-//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2
 //@ build-pass
 //@ ignore-pass (test emits codegen-time warnings)
 //@ needs-llvm-components: x86
diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-simd-abi-checks.stderr
index 9944aa093b4..95486f480d2 100644
--- a/tests/ui/sse-abi-checks.stderr
+++ b/tests/ui/sse-simd-abi-checks.stderr
@@ -1,5 +1,5 @@
 warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
-  --> $DIR/sse-abi-checks.rs:19:1
+  --> $DIR/sse-simd-abi-checks.rs:20:1
    |
 LL | pub unsafe extern "C" fn f(_: SseVector) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -13,7 +13,7 @@ warning: 1 warning emitted
 
 Future incompatibility report: Future breakage diagnostic:
 warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
-  --> $DIR/sse-abi-checks.rs:19:1
+  --> $DIR/sse-simd-abi-checks.rs:20:1
    |
 LL | pub unsafe extern "C" fn f(_: SseVector) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr
index 7a956dbfeef..9b5869fd0dc 100644
--- a/tests/ui/static/static-lifetime.stderr
+++ b/tests/ui/static/static-lifetime.stderr
@@ -11,7 +11,7 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
    |      ^^
    = note: but lifetime parameter must outlive the static lifetime
 
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/static-lifetime.rs:3:34
    |
 LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
@@ -38,5 +38,5 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0478, E0495.
+Some errors have detailed explanations: E0478, E0803.
 For more information about an error, try `rustc --explain E0478`.
diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs
new file mode 100644
index 00000000000..71d90ddd935
--- /dev/null
+++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs
@@ -0,0 +1,6 @@
+#![feature(default_field_values)]
+struct A<'a> { //~ ERROR lifetime parameter `'a` is never used
+    x: Vec<A> = Vec::new(), //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr
new file mode 100644
index 00000000000..20b9afe80cd
--- /dev/null
+++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr
@@ -0,0 +1,23 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/do-not-ice-on-invalid-lifetime.rs:3:12
+   |
+LL |     x: Vec<A> = Vec::new(),
+   |            ^ expected named lifetime parameter
+   |
+help: consider using the `'a` lifetime
+   |
+LL |     x: Vec<A<'a>> = Vec::new(),
+   |             ++++
+
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/do-not-ice-on-invalid-lifetime.rs:2:10
+   |
+LL | struct A<'a> {
+   |          ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0392.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.rs b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
index 9c8d5a5e3f6..28ae21891f3 100644
--- a/tests/ui/traits/const-traits/predicate-entailment-passes.rs
+++ b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
@@ -6,32 +6,21 @@
 #[const_trait] trait Bar {}
 impl const Bar for () {}
 
-
 #[const_trait] trait TildeConst {
-    type Bar<T> where T: ~const Bar;
-
     fn foo<T>() where T: ~const Bar;
 }
 impl TildeConst for () {
-    type Bar<T> = () where T: Bar;
-
     fn foo<T>() where T: Bar {}
 }
 
 
 #[const_trait] trait AlwaysConst {
-    type Bar<T> where T: const Bar;
-
     fn foo<T>() where T: const Bar;
 }
 impl AlwaysConst for i32 {
-    type Bar<T> = () where T: Bar;
-
     fn foo<T>() where T: Bar {}
 }
 impl const AlwaysConst for u32 {
-    type Bar<T> = () where T: ~const Bar;
-
     fn foo<T>() where T: ~const Bar {}
 }
 
diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
index 8bf8536c74e..4e324209fe9 100644
--- a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
+++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -1,4 +1,4 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
   --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28
    |
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
@@ -24,4 +24,4 @@ LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0803`.
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
index 1d42dbdfe00..294fa0d7613 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -1,18 +1,8 @@
-error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc: Sized`
+error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc == _`
   --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18
    |
 LL |     type Assoc = <T as Overflow>::Assoc;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by a bound in `Overflow::Assoc`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:7:5
-   |
-LL |     type Assoc;
-   |     ^^^^^^^^^^^ required by this bound in `Overflow::Assoc`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL |     type Assoc: ?Sized;
-   |               ++++++++
 
 error[E0119]: conflicting implementations of trait `Trait`
   --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
diff --git a/tests/ui/traits/next-solver/gat-wf.rs b/tests/ui/traits/next-solver/gat-wf.rs
new file mode 100644
index 00000000000..ff6e2665ef3
--- /dev/null
+++ b/tests/ui/traits/next-solver/gat-wf.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Znext-solver
+
+// Make sure that, like the old trait solver, we end up requiring that the WC of
+// impl GAT matches that of the trait. This is not a restriction that we *need*,
+// but is a side-effect of registering the where clauses when normalizing the GAT
+// when proving it satisfies its item bounds.
+
+trait Foo {
+    type T<'a>: Sized where Self: 'a;
+}
+
+impl Foo for &() {
+    type T<'a> = (); //~ the type `&()` does not fulfill the required lifetime
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/gat-wf.stderr b/tests/ui/traits/next-solver/gat-wf.stderr
new file mode 100644
index 00000000000..620bca77e4b
--- /dev/null
+++ b/tests/ui/traits/next-solver/gat-wf.stderr
@@ -0,0 +1,15 @@
+error[E0477]: the type `&()` does not fulfill the required lifetime
+  --> $DIR/gat-wf.rs:13:18
+   |
+LL |     type T<'a> = ();
+   |                  ^^
+   |
+note: type must outlive the lifetime `'a` as defined here
+  --> $DIR/gat-wf.rs:13:12
+   |
+LL |     type T<'a> = ();
+   |            ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.rs b/tests/ui/traits/question-mark-result-err-mismatch.rs
index 0ca18b5b0dd..df1d5105a34 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.rs
+++ b/tests/ui/traits/question-mark-result-err-mismatch.rs
@@ -1,3 +1,4 @@
+#![feature(try_trait_v2)]
 fn foo() -> Result<String, String> { //~ NOTE expected `String` because of this
     let test = String::from("one,two");
     let x = test
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr
index bad325a6720..0f83c9e73a3 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.stderr
+++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `?` couldn't convert the error to `String`
-  --> $DIR/question-mark-result-err-mismatch.rs:14:22
+  --> $DIR/question-mark-result-err-mismatch.rs:15:22
    |
 LL |   fn foo() -> Result<String, String> {
    |               ---------------------- expected `String` because of this
@@ -17,7 +17,7 @@ LL |           .map(|()| "")?;
    = note: required for `Result<String, String>` to implement `FromResidual<Result<Infallible, ()>>`
 
 error[E0277]: `?` couldn't convert the error to `String`
-  --> $DIR/question-mark-result-err-mismatch.rs:28:25
+  --> $DIR/question-mark-result-err-mismatch.rs:29:25
    |
 LL | fn bar() -> Result<(), String> {
    |             ------------------ expected `String` because of this
@@ -40,7 +40,7 @@ LL |         .map_err(|_| ())?;
    = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, ()>>`
 
 error[E0277]: `?` couldn't convert the error to `String`
-  --> $DIR/question-mark-result-err-mismatch.rs:48:11
+  --> $DIR/question-mark-result-err-mismatch.rs:49:11
    |
 LL |   fn baz() -> Result<String, String> {
    |               ---------------------- expected `String` because of this
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index c67ad762a83..818ab499306 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -10,7 +10,6 @@ LL |         Err("")?;
    = help: the trait `From<&str>` is not implemented for `TryFromSliceError`
            but trait `From<Infallible>` is implemented for it
    = help: for that trait implementation, expected `Infallible`, found `&str`
-   = note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
   --> $DIR/try-block-bad-type.rs:12:9
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index bb5e5646ad2..45422be946e 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -12,7 +12,6 @@ LL |     Ok(Err(123_i32)?)
    = help: the following other types implement trait `From<T>`:
              `u8` implements `From<Char>`
              `u8` implements `From<bool>`
-   = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:9:12
diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr
index 475bd1ff3ac..20454e12de5 100644
--- a/tests/ui/try-trait/issue-32709.stderr
+++ b/tests/ui/try-trait/issue-32709.stderr
@@ -19,7 +19,6 @@ LL |     Err(5)?;
              `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>`
              `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>`
            and 4 others
-   = note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
index 04288112fa8..ae00d3fc667 100644
--- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
+++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
@@ -15,7 +15,7 @@ note: but lifetime parameter must outlive the lifetime `'b` as defined here
 LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                     ^^
 
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error[E0803]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/closure_wf_outlives.rs:34:9
    |
 LL |         || {}
@@ -63,5 +63,5 @@ LL |     type Opaque<T: 'static> = impl Sized;
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0310, E0478, E0495.
+Some errors have detailed explanations: E0310, E0478, E0803.
 For more information about an error, try `rustc --explain E0310`.
diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr
index 7da8cfd4dbc..690592ba0b8 100644
--- a/tests/ui/type/pattern_types/range_patterns.stderr
+++ b/tests/ui/type/pattern_types/range_patterns.stderr
@@ -31,6 +31,7 @@ error: layout_of(NonZero<u32>) = Layout {
                    valid_range: 1..=4294967295,
                },
            ),
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -69,6 +70,7 @@ error: layout_of((u32) is 1..=) = Layout {
                    valid_range: 1..=4294967295,
                },
            ),
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
@@ -105,6 +107,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                ],
            },
            largest_niche: None,
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -134,6 +137,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -174,6 +178,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                                valid_range: 1..=4294967295,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -216,6 +221,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                ],
            },
            largest_niche: None,
+           uninhabited: false,
            variants: Multiple {
                tag: Initialized {
                    value: Int(
@@ -245,6 +251,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                            memory_index: [],
                        },
                        largest_niche: None,
+                       uninhabited: false,
                        variants: Single {
                            index: 0,
                        },
@@ -285,6 +292,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                                valid_range: 1..=4294967295,
                            },
                        ),
+                       uninhabited: false,
                        variants: Single {
                            index: 1,
                        },
@@ -336,6 +344,7 @@ error: layout_of(NonZeroU32New) = Layout {
                    valid_range: 1..=4294967295,
                },
            ),
+           uninhabited: false,
            variants: Single {
                index: 0,
            },
diff --git a/tests/ui/typeck/issue-103899.current.stderr b/tests/ui/typeck/issue-103899.current.stderr
new file mode 100644
index 00000000000..a3a164907be
--- /dev/null
+++ b/tests/ui/typeck/issue-103899.current.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied
+  --> $DIR/issue-103899.rs:24:54
+   |
+LL | fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+   |                                                      ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-103899.rs:4:1
+   |
+LL | trait BaseWithAssoc {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/typeck/issue-103899.next.stderr b/tests/ui/typeck/issue-103899.next.stderr
new file mode 100644
index 00000000000..a3a164907be
--- /dev/null
+++ b/tests/ui/typeck/issue-103899.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied
+  --> $DIR/issue-103899.rs:24:54
+   |
+LL | fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+   |                                                      ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-103899.rs:4:1
+   |
+LL | trait BaseWithAssoc {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs
index 81ab92a8994..92356ecf288 100644
--- a/tests/ui/typeck/issue-103899.rs
+++ b/tests/ui/typeck/issue-103899.rs
@@ -1,9 +1,5 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
-//@ check-fail
-//@ failure-status: 101
-//@ dont-check-compiler-stderr
-//@ known-bug: #103899
 
 trait BaseWithAssoc {
     type Assoc;
@@ -26,6 +22,7 @@ struct DoubleProject<L: WrapperWithAssoc> {
 }
 
 fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+    //~^ ERROR the trait bound `(): BaseWithAssoc` is not satisfied [E0277]
     loop {}
 }
 
diff --git a/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
new file mode 100644
index 00000000000..2c2788a3e56
--- /dev/null
+++ b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
@@ -0,0 +1,33 @@
+//@ run-pass
+//@ needs-unwind
+// See https://github.com/rust-lang/rust/issues/135802
+
+enum Void {}
+
+// Should be ABI-compatible with T, but wasn't prior to the PR adding this test.
+#[repr(transparent)]
+struct NoReturn<T>(T, Void);
+
+// Returned by invisible reference (in most ABIs)
+#[allow(dead_code)]
+struct Large(u64, u64, u64);
+
+// Prior to the PR adding this test, this function had a different ABI than
+// `fn() -> Large` (on `x86_64-unknown-linux-gnu` at least), so calling it as `fn() -> Large`
+// would pass the return place pointer in rdi and `correct` in rsi, but the function
+// would expect `correct` in rdi.
+fn never(correct: &mut bool) -> NoReturn<Large> {
+    *correct = true;
+    panic!("catch this")
+}
+
+fn main() {
+    let mut correct = false;
+    let never: fn(&mut bool) -> NoReturn<Large> = never;
+    // Safety: `NoReturn<Large>` is a `repr(transparent)` wrapper around `Large`,
+    // so they should be ABI-compatible.
+    let never: fn(&mut bool) -> Large = unsafe { std::mem::transmute(never) };
+    let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| never(&mut correct)));
+    assert!(result.is_err(), "function should have panicked");
+    assert!(correct, "function should have stored `true` into `correct`");
+}
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs
index 01893044c27..20cc1cfe730 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.rs
+++ b/tests/ui/wf/hir-wf-check-erase-regions.rs
@@ -8,7 +8,9 @@ impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
     //~^ ERROR `&'a T` is not an iterator
     type Item = &'a T;
 
-    fn into_iter(self) -> Self::IntoIter { //~ ERROR `&'a T` is not an iterator
+    fn into_iter(self) -> Self::IntoIter {
+        //~^ ERROR `&'a T` is not an iterator
+        //~| ERROR `&T` is not an iterator
         unimplemented!()
     }
 }
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr
index 4b696dc1d1d..e4d48bf82c0 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr
@@ -34,6 +34,16 @@ LL |     fn into_iter(self) -> Self::IntoIter {
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&T` to implement `IntoIterator`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.